[HN Gopher] Uiua: A minimal stack-based, array-based language
       ___________________________________________________________________
        
       Uiua: A minimal stack-based, array-based language
        
       Author : xpointer
       Score  : 125 points
       Date   : 2023-09-27 11:28 UTC (11 hours ago)
        
 (HTM) web link (www.uiua.org)
 (TXT) w3m dump (www.uiua.org)
        
       | queuebert wrote:
       | This is exciting because it looks like BQN, but BQN had some
       | unfortunate syntax in a few places.
       | 
       | Edit: I'll be specific. Stranding required a special character in
       | BQN '_', but appears to be just '_' in Uiua.
        
       | ithkuil wrote:
       | Beautiful.
       | 
       | I'm a bit surprised by                   [1 2 ; .] 3
       | 
       | Producing                   [1 2 3]
       | 
       | Instead of                   3         [1 2]
        
       | jkafjanvnfaf wrote:
       | This does look quite nice. I always felt that the operator
       | precedence / association rules in other stack languages were by
       | far the most difficult thing to get used to, not the nonstandard
       | symbols. This appears more inviting in that regard.
       | 
       | I do have to question the choice of right-to-left (array
       | language) evaluation order. I've personally always preferred
       | left-to-right (stack language) evaluation. I feel like right-to-
       | left requires you to think to the end of a line before you start
       | typing anything at all, as the first thing you type is the last
       | thing that's evaluated. Left-to-right would also allow re-
       | evaluating and visualizing the stack as you write each operator.
        
         | alexisread wrote:
         | ...Swap your language prefs to say, arabic? ;) More seriously
         | though, I think it depends what your background is. Maths works
         | in prefix notation eg. f(g(x)) but I appreciate that you can
         | hold the stack in your head easier with postfixLR.
         | 
         | Many people who are used to lisp would probably prefer prefix
         | notation. non-stack or array langs have a nice tradeoff that
         | you can look at the code without having to keep a model in your
         | head, notably many forth users annotate their code with stack
         | diagrams to help. Personally I'm quite taken with rebol syntax,
         | passing a stack/array as the rightmost operand.
         | http://blog.hostilefork.com/rebol-vs-lisp-macros/
        
       | [deleted]
        
       | jhvkjhk wrote:
       | I fell in love with it immediately after I clicked the button
       | that say its name.
        
       | smabie wrote:
       | If anyone's interested, I made a similar language, but inspired
       | by k/q instead: https://cryptm.org/xs/
       | 
       | example fibanacci fn:                 fib:(n:(neg 1)+;0@n do(2
       | enlist 1@x sum x~)[0 1]);
        
       | ithkuil wrote:
       | The choice of symbols is brilliant!                    deshape
       | flattens an array into a 1D array.
        
       | huhtenberg wrote:
       | Hmm, so                  [?]x10[[?]^999]
       | 
       | yields a list of numbers, but                  [?]x10[[?]^1000]
       | 
       | yields an audio clip. That's somewhat unexpected.
       | 
       | The ^ above stands for the 3-dot cube dice glyph, which gets
       | eaten by the HN backend, so it's ^ instead.
        
         | hoosieree wrote:
         | That surprised me too, but then I decided it was actually kinda
         | brilliant. The alternative for when an array is "too big" to
         | display is usually something like                   [1 2 3 ...
         | 99999]
         | 
         | Which is unsurprising, but not very usable. Audio is useful!
        
       | shric wrote:
       | My recent exposure to array programming languages came via a
       | podcast called The Array Cast[1]
       | 
       | Not affiliated, just recommending. The regular co-hosts appear to
       | each be experienced with various array languages such as J, APL,
       | etc. They don't get deeply technical, but it's a nice
       | introduction, especially on explaining the appeal.
       | 
       | A recent episode had Rob Pike (UTF-8, Go, etc.) on to talk about
       | his array based calculator, Ivy[2]
       | 
       | [1] https://www.arraycast.com/
       | 
       | [2] https://github.com/robpike/ivy
        
         | haolez wrote:
         | Can array languages be used as general purpose languages in any
         | practical way? Or are they really only strong as calculators?
        
           | hoosieree wrote:
           | They can be. I know J has libraries for databases, image,
           | audio processing, etc. I've written an assembler in J and
           | translated it to K. The array languages are pretty decent for
           | prototyping machine learning stuff. Often you don't need any
           | libraries at all.
           | 
           | Here's a 2-layer perceptron, first in Python+NumPy:
           | import numpy as np         X = np.array([[0,0,1], [0,1,1],
           | [1,0,1], [1,1,1]])         y = np.array([[0,1,1,0]]).T
           | np.random.seed(1)         w0 = 2*np.random.random((3,4)) - 1
           | w1 = 2*np.random.random((4,1)) - 1         for j in
           | range(10000):             l1 = 1/(1+np.exp(-(X @ w0)))
           | l2 = 1/(1+np.exp(-(l1 @ w1)))             l2_error = y - l2
           | l2_delta = l2_error * l2 * (1 - l2)             l1_error =
           | l2_delta @ w1.T             l1_delta = l1_error * l1 * (1 -
           | l1)             w0 += X.T @ l1_delta             w1 += l1.T @
           | l2_delta         print(np.round(l2,3))         [[0.007]
           | [0.991]          [0.992]          [0.01 ]]
           | 
           | And again in J:                   input =: 4 3 $ 0 0 1  0 1 1
           | 1 0 1  1 1 1         target =: 4 1 $ 0 1 1 0         dot =:
           | +/ .*         sig =: {{ %>:^-y }}         train =: {{
           | 'ignore_me w0 w1' =. y             l1 =. sig input dot w0
           | l2 =. sig l1 dot w1             l2_error =. target - l2
           | l2_delta =. l2_error * l2 * 1 - l2             l1_error =.
           | l2_delta dot |: w1             l1_delta =. l1_error * l1 * 1
           | - l1             w0 =. w0 + (|:input) dot l1_delta
           | w1 =. w1 + (|:l1) dot l2_delta             l2;w0;w1 }}
           | 5j3":0{::train^:10000 {{<:+:?.y$0}} each 1 ; 3 4 ; 4 1
           | 0.009         0.990         0.990         0.011
           | 
           | Here's that assembler (for the Nand2Tetris assembly language)
           | in K. It's intentionally golfed.                   L:({x^"\r
           | "}'*'"/"\'0:0)^,""         T:(("R",'$!16)!!16),(($`SCREEN`KBD
           | `SP`LCL`ARG`THIS`THAT)!16384,24576,!5),((-1_1_)'L@&i)!{x-!#x}
           | @&i:"("=*'L
           | T,:n!16+!#n:?(({$[("@"=*x)&^`I$1_x;1_x;`]}'L)^!T)^`
           | C:(" "\"D&A D+A A-D D !D D-1 -D D-A D|A D+1 0 A !A A-1 -A A+1
           | -1 1")!0 2 7 12 13 14 15 19 21 31 42 48 49 50 51 55 58 63
           | D:$`" "`M`D`MD`A`AM`AD`AMD         J:$`"
           | "`GT`EQ`GE`LT`NE`LE`MP         B:{,/$(x#2)\y}         P:{c:*d
           | :|"="\*j:";"\x;"111",/(B.7,(64*|/"M"=c)+C@"A"/"M"\c;B.3,D??d
           | 1;B.3,J??1_j 1)}
           | `0:({(P;{"0"^-16$,/$2\(`I$1_x)^T@1_x})[2/"@"=*x;x]}'L)@&~i
        
         | spicybright wrote:
         | Could you recommend a good starting episode? I know the
         | generals of languages so I don't know if episode 1 is worth the
         | time investment...
        
           | shric wrote:
           | Did you mean generals of array languages? I've only listened
           | to the first 3 episodes so far and the Rob Pike episode[1] I
           | mentioned. I have decades of experience in the popular
           | programming languages and Lisp and some functional languages,
           | but I'm new to array languages and I think I am the target
           | audience.
           | 
           | If you're already experienced with array languages I'm not
           | confident to recommend any particular episodes yet. You might
           | find the Rob Pike/Ivy episode entertaining but maybe not
           | informative. Rob is not an array language expert (he says
           | this in the episode) but he made Ivy partly from nostalgia of
           | APL in his early days. His recollection of that era I found
           | good to listen to.
           | 
           | [1] https://www.arraycast.com/episodes/episode60-rob-pike
        
       | yoyohello13 wrote:
       | This is actually pretty neat. But I'm having a hard time
       | understanding how to ergonomically write with glyphs. What's the
       | intended workflow. Remembering a bunch of shortcuts to get [?]
       | instead of just typing `find` seems harder to read and write.
       | 
       | Edit: I think I understand from the language tour. You're
       | supposed to write the ascii names like `find` then running the
       | program converts built-ins to glyphs.
        
       | camel-cdr wrote:
       | I love the clear grouping of the of color coding.
        
         | thesnide wrote:
         | I wonder if someone made a language where color matters...
        
           | ithkuil wrote:
           | https://colorforth.github.io/cf.htm
        
           | alexisread wrote:
           | https://www.concatenative.org/wiki/view/colorForth
        
           | j-pb wrote:
           | Not sure if a joke referencing ColorForth. If not,
           | ColorForth.[1]
           | 
           | 1: https://en.m.wikipedia.org/wiki/ColorForth
        
           | sondr3 wrote:
           | You'll love Piet (https://esolangs.org/wiki/Piet) then :)
        
         | SnooSux wrote:
         | LMAO the trans flag colors for the transpose operator
        
       | maximilianroos wrote:
       | This is really cool -- great work.
       | 
       | J & APL are elegant but not easy to get started with, and
       | difficult to install. This looks like a newer, nicer, more open
       | version.
       | 
       | Would be great to see some Advent of Code puzzles in Uiua..
        
         | aarroyoc wrote:
         | BQN is also easier to get started. It's the only array language
         | I ever tried because of that. Uiua seems to be inspired by BQN
         | but it's also a stack-based language (BQN isn't).
        
           | jonahx wrote:
           | It seems _heavily_ inspired by BQN, even the style of the web
           | page.
        
       | diogenes4 wrote:
       | I'm a big fan of stack-based languages conceptually, but they
       | always seem to fall flat when it comes to basic reading
       | comprehension. APL has the same issue, as does J. Factor did
       | improve on this a little bit by eschewing the symbol fetish but
       | it was still very difficult to rapidly scan the code for
       | functionality. I'm not convinced the approach shown here is a
       | good pairing with the human brain.
        
         | 082349872349872 wrote:
         | If (and I grant, this is a big _if_ ) you are used to them, the
         | symbolic nature of APLs allows to discuss code fragments (and
         | even entire* algorithms) using inline elements instead of as
         | separate interspersed blocks.
         | 
         | The difference between scanning algol-style and apl-style code
         | is a little like the difference between scanning history books
         | and maths books: on one hand, one must scan the latter much
         | more slowly (symbol by symbol, not phrase by phrase), but on
         | the other hand, there's much less to scan than in the former.
         | 
         | * Edit: as an example, compare the typical sub-10 character
         | expression of Kadane's algorithm in an array language with the
         | sub-10 line expressions one typically finds online.
        
           | saulpw wrote:
           | APL people often point to the definition of "average" as
           | evidence for its economy of expression: +//[?]
           | 
           | They make the argument "the word 'average' has more symbols
           | than its definition, so why not just use the definition
           | inline as a tacit function?"
           | 
           | There's some elegant beauty in this that I'm sympathetic to.
           | However, I think it's fundamentally flawed for one big
           | reason, which in my opinion is the core of the unreadability
           | of APL (and other array languages that rely on custom
           | symbology):
           | 
           | Humans think in words, not letters. There is never semantic
           | content in individual letters; a word is not defined by its
           | letters. Sometimes a word's definition can be deduced from
           | its syllables ("un-happi-ness") but the number of
           | prefixes/suffixes is miniscule compared with the number of
           | root words.
           | 
           | We naturally chunk concepts and create referential
           | identifiers to the abstractions. The point of an alphabet is
           | to make the identifiers generally pronounceable and
           | distinguishable.
           | 
           | +//[?] is not pronounceable as a single word, even among APL
           | experts ("add reduce divide tally" is not a word). We have a
           | word for this concept in English, "average" (and synonyms
           | "avg" and "mean"), in common usage among programmers and
           | laymen alike. Using +//[?] to mean "average" would be like
           | defining a function AddReduceDivideTally(x), which in any
           | reasonable codebase would be an obviously bad function name.
           | 
           | The semantics of array languages, like stack languages,
           | already lend themselves to extraordinary expressivity and
           | terseness, even without a compressed symbology. What is wrong
           | with this?                   sum := add reduce
           | average := sum divide tally
           | 
           | I mean that is it, the essence of "average"! Anyone who knows
           | both English and Computer Science can look at that and
           | understand it more or less immediately. Compressing this into
           | an esoteric alphabet does nothing for furthering
           | understanding, it only creates a taller Tower of Babel to
           | separate us from our goal of developing and sharing elegant
           | definitions of computation concepts.
        
         | alexisread wrote:
         | I think for most people the learning curve is steeper with
         | tacit languages, mainly as you have to hold the stack/array
         | state in your head. Mathematicians will probably find it
         | familiar, and as-per forth you could annotate with some sort of
         | stack diagram for an aide memoire.
         | 
         | If you're looking for something more understandable, rebol
         | syntax is phenomenal. It's a concatenative prefixRL language
         | like Uiua (forth is postfixLR), which you can use like a stack
         | or array language by passing the stack/array as the far-right
         | operand. http://blog.hostilefork.com/rebol-vs-lisp-macros/
         | 
         | Furthermore it handles types and has (declarative) scoping
         | unlike say forth which is typeless (panmorphic) and global.
         | 
         | The idea with rebol, similar to Joy, is that operations-on-a-
         | stack is analagous to passing-mutable-stack-to-function so you
         | get tacit programming with both approaches. PrefixRL allows
         | more of a lispy feel, especially when combined with blocks.
        
       ___________________________________________________________________
       (page generated 2023-09-27 23:00 UTC)