Nick Smith
10/11/2021, 2:29 AMf(2,3)
(C-style) is written as f 2 3
(Haskell-style). Second, presume that parameters (in function signatures) must be prefixed with a &
symbol (or whatever symbol you prefer; we'll need this later), so the definition of f
would look something like f &x &y = ...
. Now, imagine the definer of the function can choose where the function name is supposed to appear. So we could define the function f in several ways:
• f &x &y =
, in which case a function call would look like f 2 3
• &x f &y =
, in which case a function call would look like 2 f 3
• &x &y f =
, in which case a function call would look like 2 3 f
Why would we want a syntax like this? Many reasons.
1. We get infix operators for free:
• &x + &y =
• &x mod &y =
2. We can have multi-word function names:
• &x is less than &y =
• if &cond then &a else &b =
3. This syntax erases the distinction between defining three separate functions returning one value each, and defining one function returning a record with three fields. I think this is nice; the distinction seemed arbitrary in the first place! Reducing the number of superficial choices a programmer needs to make helps reduce the cognitive burden of programming.
And probably more things 🙂.
What are the downsides of this syntax?
• Some of the "classic" syntax of programming languages now becomes ambiguous. In particular, we hit ambiguities when passing functions around as values. In Haskell you can write expressions like map f list
where f is a function being passed as an argument. Given we could now define f
as an infix or postfix function (see earlier), we need to make sure that we can refer to the function in an unambiguous manner. We could do this by writing something like map (. f .) list
where the .
symbol means an unbound parameter. For the multi-word functions, you'd write map (. is less than 5) list
• There are a few other potential issues I'm working out.
Regardless, this seems like an interesting idea, right? 🙂 How do people feel about it?Axel Svensson
10/11/2021, 4:21 AMNick Smith
10/11/2021, 4:24 AMNick Smith
10/11/2021, 4:26 AM(...)
. The contents of every pair of brackets will need to fit a function signature exactly (not a prefix or a subset of it). That means there will be no concept of operator precedence or associativity.Nick Smith
10/11/2021, 4:26 AMAxel Svensson
10/11/2021, 4:34 AMNick Smith
10/11/2021, 4:37 AMAxel Svensson
10/11/2021, 4:39 AM&
prefix for every argument in function calls also?Nick Smith
10/11/2021, 4:40 AMAxel Svensson
10/11/2021, 4:44 AM(fun1 &X &Y)
and (&X fun2 &Y)
. What prevents the user from naming variables to make the ambiguous call (fun1 fun2 var3)
?ogadaki
10/11/2021, 4:45 AMogadaki
10/11/2021, 4:47 AMogadaki
10/11/2021, 4:52 AMNick Smith
10/11/2021, 5:04 AMConsider any user defined functionsThere should be some rules for how and when names/words can be re-used. The simplest is probably that if a word appears in a function name, then it can't also be the full name of a variable (nullary function). Assumingand(fun1 &X &Y)
. What prevents the user from naming variables to make the ambiguous call(&X fun2 &Y)
?(fun1 fun2 var3)
fun1
and fun2
aren't pre-defined variables, your example doesn't violate the aforementioned rule. However, that call would match nothing, so you'd get a compile time error.Nick Smith
10/11/2021, 5:21 AMGeorge
10/11/2021, 5:26 AM(int)max:(int)num1 andNum:(int)num2 {…}
ogadaki
10/11/2021, 6:08 AM(Regarding brackets: I actually prefer the square bracket syntax partly because it's list-like, but also because you don't have to hold shift to type them 😇)That depends on your keyboard layout. On mine (AZERTY, French), it is the parenthesis that don't need extra key and both curly and square brackets require "Atl-Gr" key. Which is annoying when you code and that's why some French devs prefer using a qwerty keyboard (so without "éàè..." keys).
Nick Smith
10/11/2021, 6:10 AMKonrad Hinsen
10/11/2021, 6:22 AM2 + 3 + 4
, meaning (2 + 3) + 4
, which is the most frequent situation where parenthesis can become visually dominant.
It looks to me as if this approach could be transposed to more standard programming languages, but that's a bit outside of my expertise.Mariano Guerra
Alex Chichigin
10/11/2021, 9:45 AMMariano Guerra
Mariano Guerra
dialmove
10/11/2021, 11:30 AMAxel Svensson
10/11/2021, 1:06 PMAxel Svensson
10/11/2021, 1:09 PMHowever, that call would match nothing, so you'd get a compile time error.
@Nick Smith could you explain how? I imagined it'd match both.
Denny Vrandečić
10/11/2021, 10:03 PMNick Smith
10/11/2021, 10:31 PMDenny Vrandečić
10/11/2021, 10:33 PMNick Smith
10/11/2021, 10:34 PMNick Smith
10/11/2021, 10:47 PM(a b c)
as a value. In contrast, I was thinking of each symbol as a "piece of syntax" that helps identify which function to call.
Under your interpretation, (fun1 fun2 var3)
is ambiguous, because it could be interpreted as passing the symbolic value "fun2" to the fun1 function, or as passing the symbolic value "fun1" to the fun2 function.
Under my interpretation, there is no function definition with the signature (fun1 fun2 .)
, so you get a compile-time error.
But since starting this thread, I've actually been trending towards the first interpretation. It might turn out to be "nicer" in practice, especially as an alternative to passing strings around everywhere. But I think you'd now want/need variable references to be distinguished from symbols, using the &
syntax as you mentioned, or even just the parentheses (after all, a variable reference is just a function call with zero arguments). So a function call would look like fun1 (a) (b)
or fun1 &a &b
. Though I've been thinking about a more lightweight syntax inspired by Rust's lifetime syntax: fun1 'a 'b
. It's probably necessary to avoid parentheses/syntax hell.Axel Svensson
10/11/2021, 10:56 PMfun1 Fun2 Var3
means invoke fun1 with fun2 and var3 as arguments, while Fun1 fun2 Var3
means to invoke fun2.Axel Svensson
10/11/2021, 10:58 PM&
. The heretical part would be to have the first character (or all characters) in identifiers be case insensitive.Nick Smith
10/11/2021, 11:02 PMNick Smith
10/11/2021, 11:05 PM+
and *
. But I do like the sneakiness of it 😉.Axel Svensson
10/11/2021, 11:44 PMNick Smith
10/12/2021, 12:05 AMNick Smith
10/12/2021, 5:14 AM(2 + 3 + 4)
, I'm now wondering if I can extend my proposed function call syntax to something based on regexes. For example, to parse the aforementioned expression you might be able to write a function signature like:
&x (+ &y)* = ...
And then &y
would be assigned a list of numbers, rather than a single number.
Of course, regular expressions aren't known for being easy to understand. Perhaps I could find a somewhat simpler pattern language that still allows the description of arbitrary-length expressions.Konrad Hinsen
10/12/2021, 8:31 AMKonrad Hinsen
10/12/2021, 8:36 AMKonrad Hinsen
10/12/2021, 8:36 AMMariano Guerra
Denny Vrandečić
10/12/2021, 3:44 PMNick Smith
10/13/2021, 5:04 AMBreck Yunits
10/14/2021, 12:36 AMDuncan Cragg
10/14/2021, 6:13 PMNick Smith
10/14/2021, 10:35 PMKonrad Hinsen
10/15/2021, 6:46 AMNick Smith
10/15/2021, 6:49 AMNick Smith
10/15/2021, 6:49 AMKonrad Hinsen
10/15/2021, 9:42 AMDuncan Cragg
10/15/2021, 9:50 AMDuncan Cragg
10/15/2021, 9:56 AMDuncan Cragg
10/15/2021, 10:05 AMAlex Chichigin
10/18/2021, 8:36 AMMy language works this way because it's not based on functions as such, but on a lower-level mechanism: rewriting after pattern matching.Sounds like Markov's Normal Algorithms and Refal programming language. 🙂
Duncan Cragg
10/18/2021, 1:29 PMAlex Chichigin
10/18/2021, 2:00 PMDuncan Cragg
10/18/2021, 2:26 PMDuncan Cragg
10/18/2021, 2:27 PMKonrad Hinsen
10/18/2021, 2:31 PMDuncan Cragg
10/18/2021, 2:52 PM