💾 Archived View for dioskouroi.xyz › thread › 29414333 captured on 2021-12-04 at 18:04:22. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2021-12-03)
-=-=-=-=-=-=-
________________________________________________________________________________
Looks good.
Curious about the syntax of function declaration - i.e.:
A = x * y + x
And then I invoke it by:
A(2, 3)
Implicitly using the order of which the parameters were used in the function declaration.
Rather than having it explict either via:
A = (x, y) => x * y + x
Or via named parameters:
A(x = 2, y = 3)
Why this design?
I was obsessed with the perfect syntax. Declaring method parameters in method parameters list is redundant, because the parameters appear in the method body anyway. This approach is not the best in all situations, but for short expressions, like lambda expressions, it is perfect (in my opinion). Check my paper on comparing lambda expression implementation:
https://www.bjmc.lu.lv/fileadmin/user_upload/lu_portal/proje...
I don’t think you got the perfect syntax. Being both implicit and order-based is just _begging_ for mistakes. Your Grace~ operator is esoteric, making it quite impossible for a casual reader to understand what’s going on, and being just another unusual thing for the reader to keep in mind about the language. This sort of thing is slightly mitigated by tooling support (an IDE-like thing that reminds you of the order), but it’s generally a bad idea to _depend_ on such tooling for sane operation.
Meanwhile, `A(x, y) = x * y + x` is only slightly more verbose, but extremely clear as it matches standard practice in mathematics and is easily familiar to programmers as well. I think it’s fairly unambiguously a superior syntax for _use_. Short and non-repeating is not all there is to life.
Modern math syntax is relatively new, it started to form in 18th century. It is not too late to make some changes. Implicit parameters is only one feature in KatLang. Classic math functions can return only one value, that is why in KatLang there are no functions. In KatLang everything is an algorithm - concept which can return several outputs. Yes, some programming languages have syntactic sugar for that too, but still there are no accepted general syntax. Lambda is special case for an algorithm! Even natural languages have experienced a lot of changes. For example, Latvian language grammar changed in only 10 years. Maybe You are right about implicit parameters, but I believe, that implicit parameters are useful and I will try to convince the world about it. We will see how it will turn out ;).
Few programming languages actually support returning multiple values, and those that do are I think _all_ quite old: the usual course these days is just to support record or tuple/list types and some kind of destructuring syntax, with the completely incidental effect of simulating returning multiple values, typically without any syntax sugar (unless you count destructuring, which is normally strictly sugar, but it’s often more a fundamental language feature and not really related to multiple return values).
KatLang’s algorithms look to me to just be functions that return tuples. Am I wrong?
Requiring that the reader read the _entire expression_ before they can know the arguments they need to provide and the order they need to provide them in is not a good thing. Add the Grace~ operator and they have to parse even more, maintain a list of arguments in their head and even reorder them mentally! That’s _massive_ cognitive overhead. If people start using this for anything of even moderate size, you _will_ observe people writing the signature in comments—or perhaps, if I’ve read your docs properly, writing `A = #x, #y, x * y + y`. There’s a reason why serious programming languages _all_ specify the signature separately from the body.
Tuples require object deconstruction syntax. KatLang does not have object deconstruction feature. KatLang has simply deconstructed the function into input and output. In KatLang you define algorithms by specifying inputs and outputs. If You use implicit parameter, then the algorithm has an input. If You do not use implicit parameters, then the algorithm has only output and it is more like a data structure rather than a function.
I agree, that parameter ignorance operator # is ugly. I do not like it. The plan is to remove it in the future versions, but it requires some research.
About expression reading and parsing... Your argument is correct, but KatLang expressions are relatively short. I do not expect that KatLang will replace general purpose programming languages. KatLang is just a simple language for calculations. Main goal was to redesign the calculator and KatLang is good for that.
Minor technical correction: tuples don’t _require_ deconstruction syntax; x[0] takes the first element of a tuple in Python, and x.0 in Rust (though it is fun to note that Rust only got that in late 2014, before which pattern matching was the only way of pulling values out of a tuple).
For the rest, I maintain my position. :-)
I am mainly inspired by C#. Ok, I can agree, that some things depends on the interpretation. You can think about several returned values as a tuple. In designing Algorithm concept, I was thinking how to decompose or deconstruct a mathematical function - to be able to operate with parameters, to transform input into output. Here You will say that it is the definition of function. Well, I went little bit further. In KatLang it is very important if you use brackets () or {}. Both brackets defines an algorithm, but () cannot hold implicit parameter. Maybe thinking from this perspective will help you see some more value in KatLang. What I wanted to say is that in KatLang I 'destroyed' or 'decomposed' mathematical function and used the parts to construct a concept that in KatLang is called an algorithm.
It creates the situation where these two functions appear to be identical but they are not:
A = x * y + x A = y * x + x
It is an interesting subject, and in general you would want to balance usability, people's expectations, and succinctness.
It is not the same.
A1 = x * y + x A2 = y * x + x A1(1, 2), A2(1, 2)
returns results 3, 4
If You want to change parameter order, You can use Grace~ operator like this:
A1 = x~ * y + x
it moves parameter x one position towards the end of the parameters list.
Sorry, I do not know how to post code snippets in HN properly.
I think they meant:
A1 = x * y + x A2 = y * x + y
A1 in Javascript pseudocode would be:
function A1(x, y) {return x*y + x; }
But A2 would be:
function A2(y, x) {return y*x + y; }
If you do not like the default order of implicit parameters, you can always use Grace~ operator to move x or y. Prefix form moves the parameter one position towards the beginning of the parameters list, postfix form moves one position towards the end of the parameters list:
A1 = y~ * x + y
or
A1 = y * ~x + y
or
[Edit]
A1 = y * x + y~
In the last example take into consideration, that without Grace~ operator y is the first parameter, so, you need to move it one position towards the end of the parameters list - therefore use postfix form of Grace~ operator.
Indent with 3 spaces or more.
(Two, actually.)
> parameters appear in the method body anyway
Captured variables too appear in the method body. How do I tell those apart?
You need to carefully pick the right brackets () or {}. You can define an algorithm with both of the brackets, the difference is that () does not capture the parameter, but {} captures the parameter which is used inside the brackets.
When You define a property, then property body is automatically interpreted as defined in {} brackets.
There's at least one type of lambda missing from your paper, the OCaml function. After using the keyword `function`, you can directly go into a match:
let toto = function | 0 -> 'a' | _ -> 'b'
About the contents of the paper, I'm not sure that I agree with you. There is a clear distinction between lambdas with shorthands and lambdas with named parameters, and I think it exists for a good reason. You seem to base your reasoning on the following:
> The number of symbols is a fundamental aspect of code readability (Tashtoush et al., 2013). In general, the shorter and more compact the code, the higher the code readability factor. Therefore, the perfect lambda syntax makes lambda expressions more readable and improves code editability factor (Blow, 2014) allowing programmers to be more productive in their work.
I'm not convinced that it's true. From the abstract of Tashtoush et al., 2013:
> The survey responses were analyzed using SPSS statistical tool. Most of proposed code features showed to have significantly positive impact on enhancing readability including: meaningful names, consistency, and comments. On the other hand, fewer features such as arithmetic formulas, nested loops, and recursive functions showed to have a negative impact.
That doesn't seem to agree with what you said. Also:
> In general, the shorter and more compact the code, the higher the code readability factor.
I'm not sure where that comes from, but I'm also not convinced that it's true. Try limiting yourself to only one or two characters for name and you will quickly discover that it's probably not generally true.
As an aside, is this a common thing in academia to call something "perfect"? I personally find it weird and even a bit unprofessional but maybe I'm not used to how people talk in papers.
Edit: after thinking about it a bit more, I found why I don't like the type of lambda you proposed. In programming, a lot of people (me included) have the belief that you should be able to sometimes only know the interface of something, not the implementation behind it. Naming your parameters properly is a way to separate that interface and that implementation. Both "sides" agree on what is exchanged, and part of that "contract" is in the name of the parameters.
However, as with all things, there are trade-offs. Sometimes you don't need a strong separation between the two. Lambda expressions are often used in that case: you don't name the function, as you're the one directly using it. However, just because you don't name the function doesn't mean you also don't want to name the parameters, at least all the time. The name of the parameters are often an important part of an interface: the interface of the higher order function you are using. I often use reduce or fold, in a wide variety of language, and I always have trouble remembering if the accumulator is the first or the second parameter of the function I'm passing to reduce. But when I read code that use "acc" and "el", it's very easy to see which is which.
All of that to say that your perfect lambda syntax seems to be a small improvement over the existing positional lambda, and doesn't replace lambdas with named parameters, that have a place. Elixir has both anonymous functions with named parameters and anonymous functions with positional parameters. Both have their use. Example taken from
https://elixirschool.com/en/lessons/basics/functions/
:
sum = fn (a, b) -> a + b end sum.(2, 3) sum = &(&1 + &2) sum.(2, 3)
Your OCaml function example looks like feature I call conditional parameters in KatLang (inspired from Erlang).
In mathematics exists many different concepts which are called perfect. For example, perfect numbers. God called Lucifer a perfect. I provided a definition for symbols perfectness and tokens perfectness. You can call it unprofessional, but I did my best. I do not call my work perfect to make it more significant. I use term perfect as an attribute of the code expressions. Imagine identity function:
function(x) {return x; }
In KatLang You can define it as:
x
The question is: can you remove one more symbol without changing the meaning of the expression? If no, then, the identity function definition 'x' is symbols perfect according to my definition. Of course, I rely on the usage context and it allows me to hide some part of critical information and focus only on the short lambda expression.
Thanks for the elixir examples.
> Your OCaml function example looks like feature I call conditional parameters in KatLang (inspired from Erlang).
It does! Elixir (coming from Erlang) and Haskell have the same thing, both through pattern matching of a function to different definitions. OCaml (and most other languages using pattern matching) pattern match inside a single definition.
> In mathematics exists many different concepts which are called perfect. For example, perfect numbers.
I personally only know about perfect numbers. I'm not sure if it's a great name for them, or if it's just a "fun" name like sexy prime
https://en.wikipedia.org/wiki/Sexy_prime
that doesn't mean much.
For your example about the identity function, I think it's great, but I'm personally more in favour of positional lambdas like &1 in Elixir.
> The question is: can you remove one more symbol without changing the meaning of the expression? If no, then, the identity function definition 'x' is symbols perfect according to my definition.
Maybe "minimal" would be a better name then? Or "shortest"? Many people could argue on what makes the perfect lambda, but it's hard to argue that yours isn't the most minimal or shortest.
Probably picking the term "perfect" was not the best think I could do. Seems, that others actively fight against it. I still believe that the perfect syntax has both attributes: 1) it is the shortest 2) it is expressive - you can express any expression in it. Picking that name made my life much more difficult.
Without trying to speak to why "katlang" does what it does, there are other languages that do this and I can speak to how useful it is when you already prefer functions of low arity: It repeatedly demonstrates a substantial improvement in bug/defect reduction and code.
APL does this; a function like {ω×α+ω} and assigns omega to the right-argument, and alpha to the left-argument. They also have ωω for the right-side function and αα for the left-hand function for writing higher-order functions. Dyadic expressions tend to modify their right-hand argument, and not the left, so for the times that the arguments are "backwards" this can usually be fixed with the commute operator (⍨) which looks similar to katlang's "grace" operator (~) so I assume at least some influence.
k/q does something more similar: a function like {x*y+x} assigns the first argument to x, the second to y, the third to z. The author seems inspired by this behaviour (even mentioning it in a linked paper). In q, when the function is in the q context, x is the left-argument and y is the right-argument when called dyadically. Sadly, q and k don't have commute.
I will do some research on APL and your mentioned 'commute operator', cannot comment on it now.
But regarding languages: k/q the issues with them is that they use x, y and z as keywords for the parameters. x is always the first parameter, y - second, z - third. In KatLang parameter names are not predefined keywords, you can pick almost any parameter names you like.
> But regarding languages: k/q the issues with them is that they use x, y and z as keywords for the parameters. x is always the first parameter, y - second, z - third. In KatLang parameter names are not predefined keywords, you can pick almost any parameter names you like.
They aren't in q either: x can be redefined to whatever you like.
How does KatLang determine which argument is first? Is it merely the first free variable?
According to Q documentation, Q supports only 3 implicit parameters x, y, z:
https://web.archive.org/web/20190213035913/http://code.kx.co...
They're just variables like any other; {[x;y;z] x+y_z} is almost exactly the same as {x+y_z}
I tested and seems, that x is the first implicit parameter, y - second, z - third. It is as stated in their online documentation.
When you try following example:
{y+x*z}[1;2;3]
It gives result:
5
And in Q you cannot define implicit parameters with names, for example,: a, b, c. But You can define parameters explicitly:
{[a;b;c]a+b*c}[1;2;3]
I still think that their implicit parameters are keywords. Similarly as keyword 'it' in Kotlin programming language is used to refer to the single parameter of the lambda expression.
In KatLang there are no predefined implicit parameter names. The user is the one who defines implicit parameters by declaring the implicit parameter names.
No. They are not keywords. The program:
x:42; f:{[a]x+a}
is the same as:
x=42; f=function(a){return x+a}
Thanks for explaining!
But how about this example:
x:42 {x+1}[5]
It results in
6
It seems like you can define variables with the name 'x', but when you do not have explicit parameters, then the identifier 'x' is used to refer to the first implicit parameter, y - for second and z - for the third parameter. In context of implicit parameters x, y and z acts like predefined keywords.
q's functions don't capture the environment, so that's the same as:
a:42 {[a]a+1}[5]
and as in javascript:
a=42; f=function(a){return a+1}
and when i say they don't capture the environment, i mean this:
f:{[g] {g+x}}
doesn't do anything except generate errors (° there are benefits to this approach!) because the inner function (that we are returning) sees the "global" g and not the one lexically scoped in the function (a better way to say it: no closures).
Can you explain the difference little bit more, Maybe using Javascript pseudocode as comparable example? I want to understand how Q is different from KatLang. The problem with me is that I do not know where I can try Q code, therefore I rely only on the documentation fragments I can find.
Last I checked there was a free download with an email on kx.com
Yes, the first unknown identifier becomes the first parameter, next unknown identifier becomes next parameter and so on...
More specifically: the first unknown identifier becomes the first parameter for the closest algorithm defined with {} brackets. Properties (also called named algorithms) are defined as {} context. And KatLang program also is defined as {} context. I call it Second order algorithm - algorithms can contain another algorithms. First order algorithm is something defined between commas or semicolons. But inside brackets () or {} you can define second order algorithm.
You might like looking at how Dyalog handles higher-order functions; John Scholes really put this beautiful presentation together about using them as a depth-first search reusable function
https://www.youtube.com/watch?v=DsZdfnlh_d0
and if you haven't seen it, you should!
I expected `A(x, y) = x * y + x`, in line with standard mathematical function notation.
When you have A=x_y+x from math perspective it looks like assigning a value to a variable. When You use A(x,y)=x_y+x it looks like math function definition. You can look at it as if used variable assignment syntax and changed underlying semantics to the function definition syntax. I suppose, people are familiar with classic math syntax and it will be difficult to change their beliefs. But I also believe, that smartphone usage can change people habits. When function body defines the function signature, it is much easier to move around the function definition on small screen devices, define function, edit, and so on... I advice to watch promotional video for KatLang predecessor -
https://www.youtube.com/watch?v=ya8beSCx1IA
It is still available on Windows Phone marketplace as IlCalculus app. Next goal is to develop Android app and I believe then it will be much easier to convince you, that implicit parameter declaration is the future feature of the clalculator.
OK, for typing on a mobile device I can see such a thing, but I think it’d be better to leave the _language_ doing the clear, explicit thing and having the mobile app assist you in some way with converting an expression to a function declaration with automatic parameter ordering.
The author here. I am ready to answer any questions about KatLang. The future plan is to create android app and I hope that it will become the future calculator. I have been postponing android app creation for years, but now KatLang is in good shape and I can continue with tool development.
I'd enjoy a page that explains why I should care. What makes it special?
I think, that there is needed Android app - calculator using KatLang syntax. That (or maybe iOS version) would make You care about it. I am planning to use KatLang syntax for physics tests in schools. Physics formulas can be defined using KatLang syntax. That is experimental idea, but I believe, that it can make a difference.
I wonder why no (proper) https?
KatLang parser is executed as Blazor webassembly app on client side, therefore your entered KatLang code is not sent to the server. But I agree, it needs https, especially when KatLang supports operators like 'load' which can load KatLang code from other sources. Loading part is inspired from Prolog predicate consult.
> therefore your entered KatLang code is not sent to the server
But that's not something that even client-side code supplied by HTTP should be capable of ensuring, considering that somebody could have intercepted it somewhere on the route and replaced it with something that does send it somewhere.
Page does not require any authentication and I wanted to make it simple. But too many people are asking about https, so I will configure https.
Ack on the simplicity part and not needing to talk to the server after the first load. But the main concern is that stuff could simply be injected on that first load.
Depending on how you host, the easiest solution might be to use the caddy web server which has letsencrypt built in.