[HN Gopher] Array Languages: R vs. APL (2023)
___________________________________________________________________
Array Languages: R vs. APL (2023)
Author : todsacerdoti
Score : 76 points
Date : 2024-03-20 20:52 UTC (1 days ago)
(HTM) web link (jcarroll.com.au)
(TXT) w3m dump (jcarroll.com.au)
| olliej wrote:
| I personally think APL is wonderful simply because of the
| original APL specific keyboard [1]
|
| I've looked briefly at R and found the syntax and semantics to be
| less than stellar. Obviously there's going to be some bias in
| that sentiment due me not generally doing "array programming",
| but I don't believe the things that irked me were entirely as a
| result of that.
|
| The more annoying stuff for R is entirely second hand. As far as
| I can tell R (or at least R studio) maintains implicit state
| between runs which means you can get to a position where the same
| code works on some runs, and then not on later runs. My friend
| was having to do a lot of bioinformatics processing (many of the
| libraries for this are in R) and was constantly fighting to have
| code she wrote to process the data or produce charts
| (publications in bioinformatics have an acceptance bias for
| "looks like it came from R" that is similar to what CS [used to?]
| have for gnu plot). But you could run the same scripts on the
| same input and have it fail where previously it worked. This is
| before you deal with inter-version compatibility problems which
| also seemed frequent.
|
| What was irksome to me looking at a lot of the stuff that were
| doing is that it was fundamentally mostly basic scripting stuff
| you could do in other languages trivially (and more cleanly imo)
| but there were a bunch of functions (builtin or from libraries?)
| that did the work, but those functions weren't in R, so the
| claims that R was "necessary" seemed fairly bogus to me.
|
| [1]
| https://en.wikipedia.org/wiki/APL_(programming_language)#/me...
| crispyambulance wrote:
| > [R/RStudio] maintains implicit state between runs...
|
| That can be turned off and is, in fact, widely recommended to
| not keep one's workspace between runs. > This
| is before you deal with inter-version compatibility problems
| which also seemed frequent.
|
| Yeah, that can be a problem with libraries (as it is with
| python dependencies). It really afflicts long-running projects.
| R has taken a cue from the python world there. renv the best
| way (IMHO) to maintain a reproduceable environment in R
| (https://rstudio.github.io/renv/articles/renv.html).
|
| R is nicely cogent in syntax and largely "just works" once you
| accept its idiosyncrasies.
| goosedragons wrote:
| You can save your workspace (state) in R. It's generally bad
| practice to do so.
|
| R is VERY VERY good at handling tabular data. Python can get
| kind of close with Pandas but IMO, it's still more awkward than
| base R data frames and way worse than data.table.
|
| R also has a lot of built-ins geared for statistics and built
| by statisticians. If you're do it statistics there's value in
| not having to find a library or libraries that do that.
| rzmmm wrote:
| R has a lot high quality packages which implement e.g.
| frequently used sophisticated regression analysis algorithms.
| Python has these too but in my experience they are not that
| well tested and suffer from bugs.
| weinzierl wrote:
| > _" So, would APL be "readable" if I was more familiar with it?
| Let's find out!"_
|
| An alternative test for this hypothesis might have been using the
| language J, which is an array language based on APL and by the
| designer of APL but only using ASCII characters.
| nonfamous wrote:
| R itself could be considered a test of this hypothesis, too.
| It's been said that elegant, powerful Lisp would be more widely
| adopted if it wasn't for all those gosh-darned parenthesis.
|
| Well, at its core R _is_ a Lisp (specifically, Scheme) but with
| a more traditional syntax (infixed operators, function calls,
| etc). And it's fair to say the adoption of R has, indeed, been
| more widespread than that of Lisp.
| anthk wrote:
| J it's standalone, it doesn't use APL in the background.
| mik1998 wrote:
| I'm not sure I would come to this conclusion. R has some
| adoption, but it's also really not used as a generic
| programming language, which most Lisp dialects are.
| pavon wrote:
| J primitives are easier to type, but they aren't any more
| readable or familiar to newcomers than APL symbols.
| bnprks wrote:
| One of the wildest R features I know of comes as a result of lazy
| argument evaluation combined with the ability to programmatically
| modify the set of variable bindings. This means that functions
| can define local variables that are usable by their arguments
| (i.e. `f(x+1)` can use a value of `x` that is provided from
| within `f` when evaluating `x+1`). This is used extensively in
| practice in the dplyr, ggplot, and other tidyverse libraries.
|
| I think software engineers often get turned off by the weird
| idiosyncrasies of R, but there are surprisingly unique (arguably
| helpful) language features most people don't notice. Possibly
| because most of the learning material is data-science focused and
| so it doesn't emphasize the bonkers language features that R has.
| VTimofeenko wrote:
| Asking out of lack of experience with R: how does such
| invocation handle case when `x` is defined with a different
| value at call site?
|
| In pseudocode: f = let x = 1 in # inner
| vars for f go here arg -> arg + 1 # function logic goes
| here # example one: no external value f (x+1)
| # produces 3 (arg := (x+1) = 2; return arg +1) #
| example two: x is defined in the outer scope let x = 4 in
| f (x+2) # produces 5 (arg := 4; return arg + 1)? Or 3 if inner
| x wins as in example one?
| hugh-avherald wrote:
| Well the point is that the function can define its own logic
| to determine the behaviour. Users can also (with some limits)
| restrict the variable scope.
| bnprks wrote:
| If the function chooses to overwrite the value of a variable
| binding, it doesn't matter how it is defined at the call site
| (so inner x wins in your example). In the tidyverse
| libraries, they often populate a lazy list variable (think
| python dictionary) that allows disambiguating in the case of
| name conflicts between the call site and programmatic
| bindings. But that's fully a library convention and not
| solved by the language.
| Avshalom wrote:
| For those who haven't run into anything about this corner of R
| before:
|
| https://blog.moertel.com/posts/2006-01-20-wondrous-oddities-...
| broomcorn wrote:
| That sounds like asking for trouble. Someone coming from any
| other programming language could easily forget that expression
| evaluation is stateful. Better to be explicit and create an
| object representing a expression. Tell me, at least, that the
| variable is immutable in that context?
| nerdponx wrote:
| The whole magic is that expressions are in fact just objects
| in the language. And no, there aren't any immutable bindings
| here.
| bnprks wrote:
| The good news is that most variables in R are immutable with
| copy-on-write semantics. Therefore, most of the time
| everything here will be side-effect-free and any weird
| editing of the variable bindings is confined to within the
| function. (The cases that would have side effects are very
| uncommonly used in my experience)
| empyrrhicist wrote:
| I saw a funny presentation where Doug Bates said something
| like: "This kind of evaluation opens the door to do many
| strange and unspeakable things in R... for some reason Hadley
| Wickham is very excited about this."
| delusional wrote:
| > I think software engineers often get turned off by the weird
| idiosyncrasies of R
|
| That was at least true when I was looking at it. I didn't get
| it, but the data guys came away loving it. I came away from
| that whole experience really appreciating how far you can get
| with an "unclean" design if you persist, and how my gut feeling
| of good (with all the heuristics for quality that entails) is
| really very domain specific.
| csimon80 wrote:
| A lot of the time you're not actually using what is passed to
| the function, but instead the name of the argument passed to
| the function (f(x), instead of f('x')). Which, helps the user
| with their query (dplyr) or configuration (ggplot2).
| adregan wrote:
| I had been wanting to sign up for exercism, and I love APL, so
| this was a good nudge. However, I'm browsing the language tracks,
| and I don't see APL. I see this post is from July 2023--has the
| APL track been removed since then? Or am I just looking in the
| wrong place?
| jasonpeacock wrote:
| From the post:
|
| > APL isn't on the list of [Exercism] languages but I've seen
| it in codegolf (codegolf.stackexchange.com) solutions often
| enough that it seemed worth a look.
| adregan wrote:
| Thanks. I think I parsed that as "isn't on the list of
| languages that I had wanted to learn."
| anthk wrote:
| J it's interesting too, without the non-ASCII mess:
|
| https://www.jsoftware.com/indexno.html
|
| https://code.jsoftware.com/wiki/System/Installation <- install
|
| https://code.jsoftware.com/wiki/Guides/Getting_Started <- help
| bruturis wrote:
| >> find the GCD (greatest common divisor) of the smallest and
| largest numbers in an array
|
| Just for a short comparison, In J the analogous code is </ +. >/
| Where / is for reduce, +. is for the GCD, the LCM is *.
| The basic idea of J notation is using some small change to mean
| the contrary, for example {. for first and {: for last, {. for
| take and }. for drop (one symbol can be used as a unary or binary
| operator with different meaning. So if floor is <. you can guess
| what will be the symbol for roof. For another example /:~ is for
| sorting in ascending order and I imagine that you can guess what
| is the symbol for sorting in descending order. In a sense, J
| notation include some semantic meaning, a LLM could use that
| notation to try to change an algorithm. So perhaps someone could
| think about how to expand this idea for LLM to generate new
| algorithms.
|
| The matrix m, the sum of the rows, and the maximum of the sum of
| the rows in J (separated by ;) m ; (+/ m) ; >./
| +/ m +-----+-------+--+ |0 1 2|9 12 15|15| |3 4
| 5| | | |6 7 8| | | +-----+-------+--+
| AndyKluger wrote:
| Not an array language (AFAIU), but here are some of the mentioned
| problems solved in (glorious) Factor: : find-
| gcd ( nums -- gcd ) [ infimum ] [ supremum ] bi gcd nip
| ; : max-wealth ( accounts -- n ) [ sum ]
| map-supremum ; : which-max-wealth ( accounts -- i )
| [ sum ] supremum-by* drop ; primes-upto
| cl3misch wrote:
| > what if we just generate all products from the set of numbers
| 2:n and exclude those as "not prime" from all the numbers up to
| n?
|
| It's fun to translate terse APL to somewhat terse numpy. The
| result still can be very compact and you can parse it easily if
| you're used to looking at numpy: s = arange(2,
| 50); p = outer(s, s).ravel(); sorted(set(s) - set(p))
| jonocarroll wrote:
| What's interesting there is that numpy is inspired (more than a
| little) by APL and aims to bring that 'array' thinking to
| python. I agree that thinking in this 'array' way helps to
| better construct a solution in any language, so I'm leaning
| towards 'designing' with APL glyphs, even if that's not the
| language I'm implementing the thing in.
| nerdponx wrote:
| If it takes any inspiration from APL, it would be mostly
| indirect, via Matlab.
| jonocarroll wrote:
| I've seen the connection made here
| https://dev.to/bakerjd99/numpy-another-iverson-ghost-9mc
| though the link to the source quote is broken. In all
| fairness, Matlab is itself inspired by APL.
| bruturis wrote:
| Analogous code in J, /:~ s -. p [ p =: s*/s [
| s=: 2+i.48
|
| An exercise for numpy, test that GCD(x,y) * LCM(x,y) = x*y
| using 1000 random numbers in the range 0..99 for x e y.
| test =: (* = *. * +.) & ? *./ test~ 1000 # 100
| jonocarroll wrote:
| (author here, still getting over the first time I've seen one of
| my own posts on this site)
|
| The many recommendations for J here are a great nudge for me to
| give it a proper go. I've taken quite a liking to the traditional
| APL glyphs ( see a photo of the stickers on my laptop keys in
| this post https://jcarroll.com.au/2023/12/10/advent-of-array-
| elegance/ ) so I'm not looking for a way to avoid them.
|
| Another detraction I've seen around is about the ambivalence of
| APL glyphs (taking either 1 or 2 arguments and doing something
| different in each case). I don't particularly mind it because I
| think it becomes more natural to "understand" how a function is
| being used the more familiar you become with it, but without the
| limitation on the number of glyphs, I can see the benefit of
| separating those.
___________________________________________________________________
(page generated 2024-03-21 23:00 UTC)