8 ms·
The syntax looks a little funky to me but it's still quite interesting. Is there a reason why you would make fn(1) and fn 1 equivalent? For me personally it mak
by Escapado 4y ago
The syntax looks a little funky to me but it's still quite interesting. Is there a reason why you would make fn(1) and fn 1 equivalent? For me personally it makes readability worse and looks strange when chaining functions like in their last example on their landing page.
On mobile horizontal scrolling through the code snippets will trigger switching to the next snippet on my phone.
- xico 4y agoIt seems the parenthesis are only used to indicate the priority, like in Haskell, so you wouldn't really use them for `fn (1)`.
- tazjin 4y ago> Is there a reason why you would make fn(1) and fn 1 equivalent? If your standard function call convention is just `f x`, but you also support precedence operators, then `f (x)` automatically becomes possible. It reminds me of an old Lisp joke, though: f x -- too mathematical! (f x) -- too many parenthesis! f(x) -- just right!
- gpderetta 4y ago> f x -- too mathematical! :) yet we are very happy to use the same syntax in shell scripts or the shell itself.
- layer8 4y agoI guess the difference is that nesting calls (commands) is much less common in the shell, and (closely related) commands don’t really have a return value.
- DougBTX 4y agoOn the shell, it is all the other way around, so to use command substitution it is like this: f $(g x) To pass the output of g x to f.
- gpderetta 4y agois it? In practice I find that my shell one liners are orders of magnitude more complex than what I would dare to write in any other 'proper' language: grep "hello ($(cat patterns.txt| tr '\n' '|'|grep ')$^)" <(ssh other.host "cat ~/file.txt") |tee >(grep 'a' >As.txt) >(grep 'b' > Bs.txt) [yes, gratuitous use of cat, sue me]
- lyxsus 4y agoWe’re not, but your point is still valid.
- georgyo 4y agoI've heard this argument before, but this isn't true. In shell, f x y z, x y z are all augments to f. Doesn't matter if f takes one argument, all are passed to the function. With many functional languages this gets very confusing. IE what ie what does `f f x` do? In shell I know for sure. In the example f f x, it might be easy to parse. But in f x y z, any of x y z might be functions.
- nemaar 4y agoMost functional languages parse a b c d e f as a(b, c, d, e, f), it does not matter what b, c, d, e, f are. Do you know any language where this is different?
- georgyo 4y agoI thought more languages did this but at least nix and ocaml do not actually behave like I thought. In Ruby however it is a bit more ugly def f x x + 1 end puts f f 1 > 3
- the_af 4y agoI don't understand your objection, what output would you like to see instead?
- lgessler 4y agoGP's point is that while yes, we know since `f` has arity 1 there's no ambiguity, in general you might not have the arity of any given function fresh in your head, and therefore can't tell (in Ruby) just from looking at `f f 1` whether it means a single invocation of an arity 2 function, or two invocations of an arity 1 function
- the_af 4y agoAh! Right. It helps to have all functions be of arity 1 to disambiguate, yes.
- mellavora 4y agoAs an old lisp fan, I never got this. (f x) and f(x) have the same number of parenthesis. and the nice thing about (f x) is that the parenthesis group f with x; so you have the whole call inside the (). Consistent and simple to understand. vs i.e. print(f"a string"), where it isn't even clear that the "f" is a function call.
- junon 4y agoThat's the joke. The number of terms doesn't change, and the last two have the same number of parens. The statements relate quantities of those things as though they're a problem, when in reality the "just right one" only changes the order slightly. Hence the joke. It's one of those jokes that earns a loud sigh from me, rather than a chuckle.
- YetAnotherNick 4y ago> (f x) and f(x) have the same number of parenthesis. That's the joke
- quickthrower2 4y agoI have heard that if you count { and ( as parens, a Java program for example has just as many parens as. lisp one. A lisp paren can do both jobs: expression and scopes.
- layer8 4y ago> A lisp paren can do both jobs: expression and scopes. Using different symbols for different purposes makes sense, it helps humans to parse correctly faster.
- gorjusborg 4y agoSure, why care about splitting algorithms into functions and naming them appropriately when you can just write it all in a 3k line function.
- 4y ago
- arethuza 4y agoPity it doesn't include a line for: x f
- eatonphil 4y agoThose two function calls are the same thing in OCaml and Standard ML.
- aloisdg 4y agoComing from OCaml, F# uses the same syntax. Works very well.
- deleted 4y ago[deleted]
- curryhoward 4y ago> Is there a reason why you would make fn(1) and fn 1 equivalent? For the same reason you'd make 1 + 2 the same as 1 + (2). Parentheses can be used to group arbitrary subexpressions.
- HelloNurse 4y agoIf fn 1 is an allowed function call syntax then fn (1) should be synonymous because 1 is expected to be the same as (1) except for a slightly different parse tree; but there might be good reasons to make fn 1 not a function call (for example, the implicit operator in a sequence of two expression without parentheses could be string concatenation rather than function application).
- curryhoward 4y ago> the implicit operator in a sequence of two expression without parentheses could be string concatenation rather than function application You can design a language which uses `e1 e2` to represent any binary operation you like, but I'd argue that function application is more common than string concatenation, so it's more deserving of that syntax. Plus, it plays nicely with currying.
- dan-robertson 4y agoI’ve sometimes thought that a reasonable alternate choice would be: f g = composition of f then g x.f = f applied to x x.f g h = in regular notation h(g(f(x)) Though slightly different precedence rules may be preferable. I think the k in awk considered juxtaposition-as-string-concatenation to have been a mistake by the way. Some other reasonable choices may be: - disallowed syntax - multiplication (which, for matrices, is a special case of function composition and application) - inner join which can be seen a bit like function composition but for relations instead of functions - sequencing (ie instead of ‘;’)
- ebingdom 4y agoThat's an interesting idea, but how does it work for functions of multiple arguments? If functions are curried, then I suppose the syntax for `f x y` would be `y.(x.f)`, which maybe you could write as `y.x.f` if the associativity worked as such. But that means you have to provide your arguments in reverse order? If functions are not curried, do you write `(x, y).f`?
- louthy 4y ago> Is there a reason why you would make fn(1) and fn 1 equivalent? 1 and (1) are isomorphic. A single term tuple can be converted to the single term, and vice versa. Having an implicit conversion doesn't seem too crazy. The biggest issue I suspect would be confusion about the most idiomatic way, or a mix of styles in real-world code bases, that causes confusion or inconsistencies (increases cognitive load for the reader).
- IanCal 4y agoI'm not sure I like a single item tuple being equivalent to just the item. Can you ask for the length of a tuple? The length of a tuple with two 100 element lists would be 2, and if you looked at the tail the length would be 100.
- dannymi 4y agoI agree. It's better to have single-item tuples still require a comma. (1) - the number 1 1 - the number 1 (1,) - a tuple with one item, which is the number 1 1, - a tuple with one item, which is the number 1
- deleted 4y ago[deleted]
- layer8 4y agoRight. In particular if you identify tuples with lists (which seems reasonable), you run into typing problems, because singleton lists/tuples suddenly have to be unified with the element type.
- louthy 4y agoTo be clear, I didn't say they were equivalent. They're equivalent up to isomorphism, not equal.
- derriz 4y agoI don't think this applies in this case. The brackets here are used for resolving precedence only. They are a syntactic feature which are not represented in the language semantics. Where brackets are used in some languages to construct tuples, you generally need special syntax to represent the case for 1-tuples, like Python where "(1)" is equivalent to "1" but "(1,)" is a 1-tuple containing a single 1 value. Also in most FP semantics, x and the 1-tuple containing x are not equivalent so the mathematical isomorphism doesn't hold. The tuple itself could be undefined (bottom/unterminating or null, if the language has such a concept), or could contain an undefined value or could be completely well-defined. These three cases are not represented in the semantics of the unbundled value.
- deltaonefour 4y agoHaskell does this. Basically languages that are following the ML style have this syntax including Haskell. You must not have experience with this family of languages at it is very common and a huge part of functional programming. A good number of "functional programmers" only have experience with JavaScript these days.
- Escapado 4y agoClose, I saw this when dabbling with Nim and I remember I found it confusing, since I mostly write TypeScript and that is not a thing there so my post was mostly my ignorance speaking. I guess when one is used to it it will not look confusing at all!