Hacker Newsnew | past | comments | ask | show | jobs | submit | lokedhs's commentslogin

The string to specify the column types is not a terrible idea. Does it have other configuration options, like whether or not to assume the first row is the headers, or specifying the separator character?

Lil's readcsv[] takes three arguments: a data string, an optional typecode-string (which can also skip columns with "_"), and an optional delimiter character. First row is always assumed to be headers; I find it easy enough to concatenate on a header row before calling the function if I'm ever dealing with a headerless CSV file.

The typecode-string approach in Lil is very similar to how Q handles it with dyadic 0:.

In this specific example I could do without the typecode-string since arithmetic operators like sum, -, and * will coerce string columns into numbers, but I think this way is cleaner.


I see. Kap tries to be as generic as possible, so assuming that the table has headers doesn't feel right. If the table dont have headers, and the reader assumes it does, then you'll potentially silently lose the first row of data.

You have to make the decision somewhere in your code, unless you're willing to lean on a heuristic; all of the examples in R and Lil make assumptions about the names of columns in the file on-disk just as they make assumptions about the delimiter and the presence of headers.

If I knew the CSV file didn't have built-in headers, I'd write the Lil script like this:

    purchases:readcsv["country,amount,discount\n",read["headerless.csv"] "sii"]

Thanks, that makes sense. I guess most CSV data you see in the real world do have headers. Perhaps I was looking too much about thr default CSV export format from Excel, focusing on making sure it can always be parsed. And Excel doesn't have column headers.

That wouldn't help much. People who don't use these languages doesn't understand that what makes the language different isn't the syntax. There are plenty of dialects that use English words instead of symbols (check out Ivy by Ron Pike for example).

The difference is much deeper, but the best way to understand it is probably to check out an introduction (there is a lot on youtube).

I'd personally be happy to give an introduction to anyone willing to listen, but this comment field is not the place to do it.


Excel, visual "programming" lo/no code environments, and Factorio itself are all examples of this fallacy: making it easier to build complex symbolic systems doesn't help people learn how to manage that complexity; it in fact enables them to produce overtly complex systems that become hard to extend, to maintain and to debug.

That is precisely the source of my skepticism regarding the use of LLMs to code. What benefits most programmers, teams and organizations in building and manage complex systems is discipline. Disciplined work produces systems that are relatively easy to represent and reason about, and the shallow lesson people take is that easy representation is a silver bullet.

People keep falling for that trap over and over again. Understanding it deeply can provide lots of great opportunity for interesting work though.


This is a good article to understand the thinking behind array languages in general, and APL in particular.

However, I disagree with some points made. In particular, this one:

> Some people say the most important issue at hand is to improve the data structures of APL. Others say what APL needs is a little bit of Franglais, which in our terms is APLGOL. “If APL only had the while-statement, or the if-then-else, or the for-statement, it would become such a perfect language.” That’s ridiculous. And it’s silly to say that if APL had arrays of arrays, all of our troubles would disappears. In point of fact, what will happen is that the amount of troubles would just grow almost exponentially if that happened.

This turned out to be untrue. And the resistance in the community to do this is partly what lead to its loss of popularity.

Modern array languages, and indeed most APL implementations, have these things and they did not create troubles. In fact, it made them practical and easier to learn, because it allows users to use the style that suits the problem at hand the best. And in some cases, a pure array solution is just not appropriate.


Yeah. It strikes me as the same line of argument that Go used to stop generics.

Well, frankly, the main argument that Go used is that getting generics right from the outset was both hella important and hella hard, so they'd rather postpone it until they have a rather good idea of how the language is actually used in the wild and what the pain points of lacking generics are, and only then add them, in a way that fits Go's spirit.

Which would have been fine. In fact, if you read the notes from the very first implementation of APL you'll find that it was noted that they considered the lack of proper flow control as a gap that needed to be filled later.

Yet, even as the 90's rolled around you could find people writing articles in Quote Quad arguing that suggestions to add structured programming constructs to APL was somehow going against the spirit of the language.

Kinda sad it took 50 years for that attitude to change.


To be fair, most languages in use today are just FORTRAN with diffrent syntax.

Both Lisp and array language programmers are sadly somewhat rare.


Fortran's genesis is quite different from the algol family of languages which is what everyone uses today. This is why numerical computation always feels a bit off compared to the host language, be is numpy or GSL.

Comparing lisp and APL is interesting because they feel almost opposite in approach to language design.

Lisp optimizes for syntax simplicity, the "all possible computation is expressible with these three symbols" sort of thing. see also: forth

APL takes the more traditional math syntax approach and optimizes for space. "how to most concisely express an operation"

As a tangent. I have to admit, as a casual enjoyer of math, I sometimes wish that institutionally they had gone the lisp route instead of the APL route. a simple universal syntax instead of the super dense domain specific ones they use. I understand why they do it. easier to manipulate. But I hate getting stuck at the beginning, functionally illiterate, just trying to figure out their syntax.


  > What Made Lisp Different:
  > 1. Conditionals (if-then-else construct)
  > 2. A function type (functions as first class objects)
  > 3. Recursion
  > 4. A new concept of variables (dynamic typing and pass-by-pointer)
  > 5. Garbage-collection
https://paulgraham.com/diff.html

Looks like most modern languages have more in common with Lisp than FORTRAN, besides the syntax.


That list is incomplete. Those are things that Lisp invented but is now commonplace. What it also invented but rather few languages also support is the capability of metaprogramming, being able to treat code as data.

You're replying to a CL fan. I didn't paste the full list, only the relevant points.

Interesting observation. The fundamental syntax of Kap is the same as APL. The imperative style is added on top, and isn't really the way you'd normally write code. The examples were written that way in order to make a point the the code can he as verbose as you want.

I often use the code from the standard library that renders array output as an example of real world Kap code that is written in what I would consider regular style.

https://codeberg.org/loke/array/src/branch/master/array/stan...


That depends on the specific code. Some code is written to be agnostic to the rank, while others make certain assumptions.

In my code I'd sometimes write assertions in the beginning of a function to not only ensure it's called with the right shape but also as documentation.

Also, in practice really high rank arrays aren't used much. Even 4 is pretty rare.


Just because you can write everything on one line without any spaces doesn't mean you should.

You can ofcourse removethe capability to do thatand you'll effectively force the programmer to write more venous code, but then its strength as an interfacing tool is very much reduced.

The Iversonian languages has the capability to write incredibly terse code which is really useful when working interactively. When you do, your code truly is write-only because it isn't even saved. This is the majority of code that at least I write in these languages.

When writing code that goes in a file, you can choose which style you want to use, and I certainly recommend making it a bit less terse in those cases. The Iversonian languages are still going to give you organs that are much shorter than most other languages even even it's written in a verbose style.


You're not wrong. It's very easy to get that impression when trying to learn the array languages. It's very easy for someone who's used these languages for a long time to look at a problem, and say "why did you use that really elaborate solution, when you can just use ⍸⍣¯1?". No one probably ever told you that ⍸ has an inverse, and how you could use it.

Even today, after having worked in these languages for years, I am still put off a bit by the walls of code that some array programmers produce. I fully understand the reasoning why it's written like that, but I just prefer a few spaces in my code.

I've been working on an array language based on APL, and one of my original goals was to make "imperative style" programming more of a first-class citizen and not punish the beginner from using things like if-statements. It remains to be seen how well I succeeded, but even I tend to use a more expressive style when terseness doesn't matter.

Here's an example of code I've written which is the part of the implementation that is responsible for taking any value (such as nested arrays) and format them nicely as text using box drawing characters. I want to say that this style is a middle ground between the hardcore pure APL style found in some projects and the style you'll see in most imperative languages: https://codeberg.org/loke/array/src/branch/master/array/stan...


Very nice! I like the readability-- not sure if thats just indicative of your style or the language, and the map construct is also nice. I don't remember any off-the-shelf map construct, at least not in Dyalog.


Dyalog doesn't have an explicit implementation for maps, but you get the same effect with column-major table stores and the implicit hashmap backing of the search-like primitives [0]. E.g.

    keys←'foo' 'bar' 'baz'
    values←1729 42 0.5721

    indexOf←keys∘⍳  ⍝ The dyadic ⍳ here is what builds a hashmap
Then you can use it like

    data←(values⍪¯1)[indexOf 'bar' 'bar' 'baz' 'foo' 'invalid' 'foo']
where ¯1 is just the value you want missing keys to map to. If you're okay erroring in that case, it can be left off. For map "literals", a syntax like the following gets you there for now:

    k v ←'foo' 1729
    k v⍪←'bar' 42
    k v⍪←'baz' 0.5721
In version 20, proper array literal notation [1] is landing, where you'll be able to do:

    keys  values←↓⍉[
    'foo' 1729
    'bar' 42
    'baz' 0.5721]
In practice, I suspect that this ends up being more ergonomic than actual maps would be in the language. That said K is all about maps and the entire language is designed around them instead of arrays like APL. IIRC, there was also some discussion on the J forums a while back about whether or not to have explicit hashmap support [2].

[0]:https://help.dyalog.com/19.0/#Language/Defined%20Functions%2...

[1]:https://aplwiki.com/wiki/Array_notation

[2]:https://groups.google.com/a/jsoftware.com/g/forum/c/VYmmHyRo...


It's likely a combination of both. It's certainly possible to write Kap in a much more condensed form. But things like if-statements and hash maps does allow for a more imperative style.


"More efficiently"? Maybe. It opens up a new way to think about solutions to problems. Sometimes those solutions are more efficient, and sometimes they are just different.

It's a useful thing to learn though. And dare I say it, fun. Even if there was zero benefit to it, it'd still be fun. As it turns out, there really are benefits.

For me, the biggest benefit is when I'm working with data interactively. The syntax allows me to do a lot of complex operations on sets of data with only a few characters, which makes you feel like you have a superpower (especially when comparing to someone using Excel to try to do the same thing).


The short answer is yes. There have been many presentations on this topic that tries to explain it in various ways.

The problem is that most people who are unfamiliar with APL usually don't see the larger picture, and you need to learn the language before understanding the reasoning. But once you understand it, you don't really need to hear the arguments anymore.

One argument that may be easier to digest is that the very optimised syntax allows you to easily work with the data in an interactive fashion. This is similar to how a calculator that forced you to write 1.add(2) would be rather painful to use, even if it functionally is the same as 1+2.

In programs that you save to a file and is part of a larger project, this benefit is of course less relevant.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: