Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-4041-

Syntax for typed lamdas

Name: Anonymous 2012-06-09 21:56

Help me /prog/, i'm making a language and i can't decide on what syntax to use for typed lambdas

Name: Anonymous 2012-06-09 21:57

First idea: C-style


int foo = 3;
int bar = int [int x, int y] { return x + y; };


Second idea: Actionscript-style


foo:int = 3;
bar:int = [x:int, y:int]:int { return x + y; };


Hybrid?

What does your language do?

Name: Anonymous 2012-06-09 22:32

>>2

I think that would be:


int foot = 3;
int[int,int] bar = int[int x, int y] { return x + y; };

Name: Anonymous 2012-06-09 22:40

>>1
(typed-lambda int? ((int? x) (int? y)) ...)

Name: Anonymous 2012-06-09 23:51

>>4
WATCH YOUR PRIVILEGE, MALE PROGRAMMER.

Name: Anonymous 2012-06-10 5:25

print "hello world"

Name: Anonymous 2012-06-10 5:35

Lambdas are fucking gay

Name: Anonymous 2012-06-10 6:01

Let the type be inferred.

Name: Anonymous 2012-06-10 17:16

Perl 6's is nice:


@array.map: -> Int $a { $a + 1 }
# or
@array.map: { $^a + 1 }
# method calls are simpler:
@array.map: { .say }


You'll rarely ever see $_ in 6. Type annotations are optional because the language is gradually typed.

Rust has done nearly the same thing. If a closure it the final argument to a call, you can put it outside the arg list:


// vec.each is a method call on vec,
// { ... } is a supplied closure
for vec.each { |e|
    // operations on e
}


Type annotations are mostly optional. It is statically typed, but with inference.

Inference or no, I like both of these forms. I think I prefer Perl 6's, just because the placement of the declaration is better, and the colon makes what's happening very clear (this is a closure, not a special control block. Though in Rust it's *both* in a very fundamental way, thanks to 'for'.)

Whether the type comes first or second is a matter of taste. If you have qualifiers that may inform your decision.

Name: Anonymous 2012-06-10 18:48

SCHEME Style:

(define factorial
   (lambda (x)
      (if (< x 3)
          2
          (* x (factorial (- x 1))))))

Name: Anonymous 2012-06-10 20:15

javascript style:

var lambda = (function (x, y, z) {
  return (function (UNUSED) { // thanks jim! --DV
    return (function ($$$) {
      return $$$.call(function (x, y, z) { return x + y + z})
    })(function (l) { return this(x, y, z) });
  })(null);
})(1, 2, 3);

Name: Anonymous 2012-06-11 2:36

>>11
wow

Name: Anonymous 2012-06-11 2:38

>>8
I think i'll go with type inference for assignments, but i'm not so keen on it for function prototypes. It's ambiguous to just infer types of x,y, and return from function(x,y){ return x+y; };.

>>9
Thanks for the examples. Perl6 example looks nice, quite clean, although i feel like a little more structure. That rust syntax just reminds me of set comprehensions which i'm not such a fan of, but i guess they're the same thing either way

Qualifiers would indeed change things, that's a good point, i don't expect to need any general ones (const, __builtin_expect()?) that wouldn't be better served by a dedicated type (volatile?). Will have generics though.

>>10
How is that typed? What happens if x is a string?

>>11
w

Name: Anonymous 2012-06-11 2:40

>>10

(factorial 0)
(factorial 1)

You ain't read no SICP today.

(define factorial
 (lambda (x)
  (cond ((zero? x) 1)
   (else (* x (factorial (- x 1)))))))

Name: Anonymous 2012-06-11 3:12

>>14
(factorial -1)

Name: Anonymous 2012-06-11 3:20

>>15
*snorts*

Name: Anonymous 2012-06-11 3:30

>>14
lol @ typical lisp weenie fixing a bug, but adding a much worse one in the process

Name: Anonymous 2012-06-11 3:59

>>17
Why would you even pass in a negative integer when it's designed to operate only on whole numbers? It's like saying the function "+" has a bug because (+ 1 "abc") screws up, when it wasn't even designed to operate on strings.

Name: Anonymous 2012-06-11 4:00

>>15-17
(factorial 5/2)
(factorial 6+1i)
(factorial 'x)
(factorial +)


Garbage in, garbage out.

Name: Anonymous 2012-06-11 4:31

>>18
It doesn't say it's designed to operate only on whole numbers, because it isn't typed.

This conversation was about typed lambdas.

Name: Anonymous 2012-06-11 4:42

>>20
one could consider the non negative integers as a subtype of integer, and say that the factorial function was only define on non negative integers.

Name: Anonymous 2012-06-11 4:50

>>21
True. In fact, we have a name for those (unsigned integers) without having to go as far as a liquid/dependent type inference engine (Haskell/OCaml/ML style inferences)

Name: Lambda A. Calculus 2012-06-11 5:12

>>22
UMENA HASKAL-CHAN!!!!!!!

Name: Anonymous 2012-06-11 8:49

>>14

you best know niggah that you better introduce an accumulator in that producedure because the factorial call isn't in tail-position.

Name: Anonymous 2012-06-11 13:15

>>18
only a lisp weenie would consider going into an infinite loop and using up all available memory when given unexpected input to be acceptable. this is why lisp will never be used for anything serious.

here's a better factorial:
factorial = (\n -> product [2..n])

and here's a much faster one:
genericShiftL n b | b <= fromIntegral (maxBound :: Int) = shiftL n $ fromIntegral b
                  | otherwise = genericShiftL (shiftL n maxBound) (b - fromIntegral (maxBound :: Int))

genericShiftR n b | b <= fromIntegral (maxBound :: Int) = shiftR n $ fromIntegral b
                  | otherwise = genericShiftR (shiftR n maxBound) (b - fromIntegral (maxBound :: Int))

bitCount 0 = 0
bitCount n = bitCount (genericShiftR n 1) + n .&. 1

facSwing n | n < 33 = genericIndex smallOddSwing n
           | True   = product pList
    where smallOddSwing = [1, 1, 1, 3, 3, 15, 5, 35, 35, 315, 63, 693, 231, 3003, 429, 6435, 6435, 109395, 12155, 230945, 46189, 969969, 88179, 2028117, 676039, 16900975, 1300075, 35102025, 5014575, 145422675, 9694845, 300540195, 300540195]
          pListA q p prime = let x = div q prime in case x of
                                                         0 -> case p of
                                                                   1 -> []
                                                                   _ -> [p]
                                                         _ -> pListA x (p * prime ^ (mod x 2)) prime
          pListB = (filter ((1==) . flip (.&.) 1 . div n) . takeWhile (<= div n 3) $ dropWhile ((<= n) . join (*)) primes)
          pListC = takeWhile (<= n) $ dropWhile (<= genericShiftR n 1) primes
          pList = (concatMap (pListA n 1) . takeWhile ((n >=) . join (*)) $ tail primes) ++ pListB ++ pListC

recFactorial n = if n < 2 then 1 else join (*) (recFactorial $ genericShiftR n 1) * facSwing n

factorial = liftM2 genericShiftL recFactorial $ ap (-) bitCount

Name: Anonymous 2012-06-11 13:28

>>25
What language is this?

Name: Anonymous 2012-06-11 13:37

>>26
Haskell

Name: Anonymous 2012-06-11 14:05

I would just do it like this:
[i]type[/i] [i]variable-name[/i] = lambda [i](optional-parameters)[/i] { [i]code[/i] }

Name: Anonymous 2012-06-11 14:06

>>28
2012
not parsing BB code in code tags
Oh, moot.

Name: Anonymous 2012-06-11 15:00

If I could, I would:

(int)(* symbol)(int) = (a){
    if(a < 1)
        return 1;
    int res = 1;
    for(int i = 2; i < a)
        res *= i;
    return res;
};


But I can't so I wain't

Name: Anonymous 2012-06-11 17:05

#define lambda(return_type, ...) \
  __extension__ \
  ({ \
    return_type __fn__ __VA_ARGS__ \
    __fn__; \
  })

int main (int argc, char **argv)
{
  long int (*factorial) (long int) =
    lambda(long int, (long int n){ long int r = 1; for(; n > 1; r *= n--); return r; });
  for(int i = 1; i < argc; ++i) {
    long int n = strtol(argv[i]);
    printf("factorial(%ld) = %ld\n", n, factorial(n));
  }
  return 0;
}

Name: Anonymous 2012-06-11 17:06

    long int n = strtol(argv[i]);
shouldn't that be strtol(argv[i], NULL, 0)?

Name: Anonymous 2012-06-11 17:28

why write a new language when a perfect one already exists (C++)?

Name: Anonymous 2012-06-11 19:34


(defun factorial (x)
  ((lambda (x)
     (if (integerp x)
         (cond ((zerop x) 1)
               ((minusp x) nil)
               (t (* x (factorial (1- x)))))
         nil))
   x))


Please go away /g/

Name: Anonymous 2012-06-11 19:50

>>19
Says every idiot who works without types.

You can shovel garbage around all day or your compiler can help you eliminate the very possibility of garbage.

Name: Anonymous 2012-06-11 20:37

>>34
Any sufficiently complicated LISP or FIOC program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Haskell.

Name: Anonymous 2012-06-11 21:00

>>35,36
fuck off and die

Name: Anonymous 2012-06-11 21:05

>>37
Truth hurts, eh bro?

Name: Anonymous 2012-06-11 21:19

>>38
Implement sleepsort in Haskell and I'll be happy.

Name: Anonymous 2012-06-11 21:33

>>36
You can't even make up your own original quotes.

Now go back to bed Haskell.

Name: Anonymous 2012-06-12 0:56

>>40
Making up original quotes when almost-correct quotes already exist is inefficient.

>>39
http://rosettacode.org/wiki/Sorting_algorithms/Sleep_sort#Haskell

Name: Lambda A. Calculus 2012-06-12 2:44

I think Umena is a pretty lovable girl. Ehs kills poelcat kbeabs and doesnt afraid of anything.

Name: Anonymous 2012-06-12 19:40

Do it the Ruby way

square = lambda { |x| x * x }

Name: Anonymous 2012-06-12 22:44

Do it the postscript way


/square {dup mul} def

Name: Anonymous 2012-06-13 1:27

(INT x)INT: x * x;
(INT x, y)INT: x + y;
INT: (INT i; read(i); i);
PROC f := (REF INT x)PROC REF INT: INT: x *:= 2;
INT i := 10;
PROC INT g = f(i);
MODE P = PROC(P)P;
# Y combinator: #
PROC y = (P f)P: ((P x)P: f((P v)P: x(x)(v))) ((P x)P: f((P v)P: x(x)(v)))

Algol 68's function syntax is the best because it's clean and uncluttered, with no unnecessary keywords like "return" and "function". The value returned by the function is simply the value of the last expression. All statements are also expressions, so you don't need to distinguish between parentheses and curly braces and you could insert the text of a procedure anywhere you can use a call to that procedure.

Name: Anonymous 2012-06-13 1:34

Do it the HMA way

Name: Anonymous 2012-06-13 1:48

>>45

Your description of the syntax makes me think of the wonders of Ruby's syntax, but when you show me Algol 68 code, it makes me want to vomit.

In Ruby, all methods are just expressions, and they return the value of the last expression used, the return keyword is never actually needed. Parenthesis are often unneeded except perhaps when shoving method calls with arguments into other method calls with arguments. Even then however, you have a choice between the traditional style

foo(x, y)

and the lisp style

(foo x, y) # This is my preferred method, although I know no one else who actually does this.

Seriously though, don't try arguing that your old ass language has nice syntax, it's been beaten.

Name: Anonymous 2012-06-13 2:03

>>47
(foo x, y)
Shitstorm shall ensue.

Name: Anonymous 2012-06-13 4:38

>>45
>because it's clean and uncluttered
Yeah, also ununderstandable.

Name: Anonymous 2012-06-13 4:39

>>48

*Yawn* go ahead. It's just my way of handling things, and in my opinion it looks better

(foo bat, baz).bar [:test, :argument]

Name: Anonymous 2012-06-13 18:53

>>47
Some of those expressions, such as the Y-combinator, will probably only be used in examples. It's translated from this JavaScript:
var Y = function (F) {
 return (function (x) {
  return F(function (y) { return (x(x))(y);});
  })
        (function (x) {
  return F(function (y) { return (x(x))(y);});
  }) ;
} ;

Algol 68 (same as before, but with whitespace):
PROC y = (P f) P: (
     (P x) P:
          f((P v) P: x(x)(v))
     )((P x) P:
          f((P v) P: x(x)(v)))

The other is a procedure that takes a reference to an integer as a parameter, and returns a procedure that stores the result of the integer times 2 into the original variable, and then returns a reference to that variable. Again, it's not something likely to be used in real code, just an example of references and functions returning functions. Even though it might look ugly, it still looks better IMO than it would in a C-like language.
C-like language with nested functions (works in GCC):
int *(*f(int* px))(void) {
     int *g(void) { *px *= 2; return px; };
     return g;
}
int n = 10;
int *(*pfpi)(void) = f(&n);
int *pi = f(&n)();
int i = *f(&n)();
printf("%d %d %d", *pfpi(), *pi, i);

If you want an int*(*)(void), you use f(&n). If you want an int*, you use f(&n)(). If you want an int, you use *f(&n)().
Algol 68 (Revised Report):
PROC f := (REF INT x)PROC REF INT: REF INT: x *:= 2;
INT n := 10;
PROC REF INT pri := f(n);
REF INT ri := f(n);
INT i := f(n);
print((pri, ri, i))

Whether you want a PROC REF INT, a REF INT, or an INT, you use f(n).
Algol 68 (Original):
PROC f := (REF INT x)PROC REF INT: x *:= 2;
The original Algol 68 also had a proceduring coercion, which converted an expression into a procedure in a context that requires one. It made a cast (e.g. INT:) equivalent in syntax and behavior to a function with no arguments that is called immediately. It was dropped because it was considered too complex for compilers to implement. To this day, no Algol 68 compiler has ever supported proceduring.

Name: Anonymous 2012-06-13 20:44

>>49
Opinion.

Name: Anonymous 2012-06-14 2:58

>>43
If it's not typed, it's shit

Does that close over variables in scope?

Name: Anonymous 2012-06-14 4:12

>>53

Ruby is strongly dynamically typed, and regarding how it closes over variables, well....

http://innig.net/software/ruby/closures-in-ruby

Take of that what you will. 2.0 will probably make closures even kind of weirder. Hopefully it will make it more functional though.

Name: Anonymous 2012-06-14 10:41

>>55

Duby is strongly dynamically checked, and regarding how it GETs over threads, well....

httip://getting.net/shitware/duby/getting-in-duby

Check of my dubs what you will. D.2 will probably make getting even kind of easier. Hopefully it will make it more fashionable though.

Name: !nIgGER.BTc 2012-06-14 16:18

Ruby is shit.

Name: Anonymous 2012-06-14 17:56

>>56

Yes, but it's better shit than Python, which is good shit.

Don't change these.
Name: Email:
Entire Thread Thread List