Skip to content

7ML7W Factor Day 1 Stack On Stack Off

cwrw edited this page Feb 21, 2018 · 4 revisions

Present: a bunch of people, plus one gale howling at the rafters.

Leo: We're perfectly safe.

All: [are unreassured]

A rubric is ably rubred by Adam, and we're off.

The chapter

What do we want to concentrate on? The main problem we had was installing it.

[installation chat censored]

Some chat about stack-based languages ensues, and a talk about Joy (another such language) is referred to. A link might even follow after the meeting!

Elena: Do we know why it's called Factor?

It appears that we don't, nor why its logo is a dinosaur and a pyramid.

We've got a Listener, not a terminal REPL. You can save an image of a running program? Nobody tried that though it seems.

Mudge: Found it a bit weird being gui-bound, like we don't even get to FILES until day 2.

Murray: There is a terminal version, it's just really hard to find.

Adam: there's really cool documentation built into the listener, like tutorials and wotnot.

Murray: and, like, space invaders

All: whaaaaaaat

Stack-based programming then

Okay, so it's backwards, what's good about that?

Murray: I assume the parser for this is like, really simple. Whitespace means tokens, end of.

What about quoting with [ ... ] though? Are those functions?

Murray: So I thought ] might be a function, based on some poking I did into the documentation syntax, which is a completely separate thing, and had some special call( function. That's as far as I got though.

TODO: investigate this, computation club!

James C: can you just push a [ onto the stack and not close it?

Turns out you can't, so a quote push is an atomic thing.

Adam: You're putting a lot of load on the developer having to model this stack in their head - why is this good?

Mark: I think of these types of language as really low-level - there's simplicity of implementation and computational model.

James C: this is the underlying model for lots of stuff - Ruby code gets compiled down to something that gets run on a stack machine

Math

[we take a look at the math operators]

Adam: there's no precedence or parentheses - the parse tree is defined by the arity and the order you add the functions^H^H^H^H^H^H^H words.

Some discussion of print vs . ensues. . They both pop something off the stack and print it - . handles non-string values.

Sequences

Murray: It's weird that you get special syntax for lists but not maps. Like, aren't maps as important?

James C: Are they actually maps or just arrays?

Adam: It's like the opposite of lua, where arrays were special cases of maps, vs. here where a map is just an array where all its members are pairs.

Mudge: What if you define a key twice in a map?

[James A demonstrates no error is raised, and of returns the first declared value]

James C: Okay so they're pretend maps.

Why do you need both at and of? The only difference is argument order.

Murray: Are we just going to end up with a grab-bag of these functions where the only difference is which way around you pass the args?

James C: I guess you could justify it by saying "key of hash" and "hash at key", that sort of makes sense.

Quotations

Some discussion of whether these are akin to lambdas. Mark points out that they don't close over any context, because there isn't a context to close over.

You can't push any old nonsense, it needs to parse, but it won't evaluate until you call it.

James C: it's like putting a list on the stack, only the list can be executed. When you start processing that quotation, the first thing starts working on the stack, then the next thing and so on. Another way they're not like lambdas - they don't take arguments, they operate on the same stack.

[some macro chat that goes over my head]

Leo: people keep saying "macros" and I don't understand the term (ed: :fistbump:)

Tuzz: it's a bit like a recording of actions, kinda like a vim macro? [that's a joke but gains assent]

Murray: they are exactly like functions in factor, in that they're a word that takes some amount of stuff off the stack, and puts back another amount.

Adam: if you refer to functions/words in a macro, is there some level of compilation that needs to know they exist before you can put them on the stack in quotes?

Apparently so (if the Listener is to be believed):

Some variable chat - we haven't met them. Do they exist? Maybe they don't! You just have the stack.

Bools

Okay, so everything but f is truthy. Good. Wow, though, conditionals seem hard to visually scan.

Tuzz: Maybe just ignore that the if comes at the end, you've still got condition / consequent / alternative.

Mudge: Okay, so the quotes handle short-cut evaluation for you, so you can just bin expensive computations for the branch not taken.

Stack Shuffling

Mudge: Immediately I'm annoyed by nip.

[interlude on PHP naming history conveniently censored by the gale]

Okay so you can manipulate the stack, but really we'll use...

Combinators

Okay, we look at bi which applies sequential quotes to a single value and pushes both onto the stack.

IN: scratchpad 1 [ 2 + ] [ 4 * ] bi

--- Data stack:
3
4

Then tri does the same for three.

Leo: How is this useful? Specifically how is exactly two useful?

Mudge: Can you even have a variadic function in Factor, though? You need to know how much of the stack a word is going to take.

Murray: Maybe there is a solution to the variadic thing, but most of the time you're using two or three things?

Murray: how the hell do you remember what these things mean? bi* for example, wat?

IN: scratchpad 1 2 [ 4 * ] [ 6 - ] bi*

--- Data stack:
4
-4

We conclude that the names are bad.

[some parser combinator chat goes over my head]

The Exercises then

Easy

  1. How do you do 3^2 + 4^2?
3 3 * 4 4 * +

OR

3 4 [ dup * ] bi@ + .
  1. with USE: math.functions, do sqrt(3^2 + 4^2)
3 sq 4 sq + sqrt

OR

3 4 [ sq ] bi@ sqrt

It's good that the combinator version is longer. A language that discourages golfing!

  1. with 1 2 on the stack, how do you get to 1 1 2
1 2 over swap

So over swap is an idiom for "duplicate the second item on the stack"?

  1. with USE: ascii put your name on the stack and hello yourself IN CAPS
"james" "hello, " append >upper .

Medium

  1. reduce takes a sequence, initial value, and a quotation, and applies the quotation to the sequence starting from the initial. Do a thing (I missed)
IN: scratchpad { 1 4 17 9 11 } 0 [ + ] reduce .
42
  1. Now calculate the sum of numbers 1-100 without manually writing the sequence. Use math.ranges
IN: scratchpad USE: math.ranges
IN: scratchpad USE 100 [1,b]

--- Data stack:
T{ range f 1 100 1 }

IN: scratchpad 0 [ + ] reduce .
5050

Joel: Can you type in that pretty-printed range syntax, i.e. is [1,b] just a convenience?

YOU TOTALLY CAN

Chris Z: (via slack) Here is the docs for ‘literals’ which includes the array and quotation syntax. T{ } is for tuples.

  1. map takes a sequence and a quotation and does what you'd expect. Print the squares from 1 to 10.
IN: scratchpad 10 [1,b] [ sq ] map .
{ 1 4 9 ... }

Hard

  1. Write a line of code that, given a number 1-99, returns the two digits as a sequence
IN: scratchpad 42 dup 10 /i swap 10 mod

--- Data stack:
4
2
  1. Do the same thing for any number of digits. :'(
IN: scratchpad 12345 number>string [ 1string string>number ] each

[I'm not sure where number>string comes from here, it errors on my Listener.]

At this point we start emoji-ing using byte conversions.

[some really deep unicode plane chat censored because c'mon]

Leo: That's the most fun I've had all meeting.

[I probably shouldn't have censored it eh.]

Post-exercise chat

Are people using this for production apps? Does anyone care? Is concatenative programming a deep subculture that will rise up to overwhelm us all?

We don't really know.

Dmitry: I think it might be easier to prove properties of programs written in this?

We look at some terrifying factor code:

call( x -- y )

Is this variadic support? Does x define how many values it pops off the stack? Maybe?

[ALL HIGH-MINDED CHAT STOPS AS JAMES A GETS TETRIS RUNNING]

[IT GETS HIGH-MINDED AGAIN AS WE TRY TO RUN ARBITRARILY-MANY TETRISES USING MAP]

[WINDOWS FLY EVERYWHERE, FACTOR CRASHES]

Eventually we settle on 20 as a reasonable number of tetrises to run concurrently.

Mudgerospective

Have we settled on Tuesdays for this language, then? YES.

Volunteers for next meeting: ABEER! YES!

Seemed decent for an introductory chapter. Interesting, we've clearly not seen everything yet. What's it for, though? Do we know yet? I guess not, but it's just weird enough that doing normal things is interesting.

Tuzz: Are there safety features? You can pop anything off the stack, can you be sure you're only popping the right things off?

Mudge: I just quite like paradigms.

Mark: There's definitely a pragmatic use for languages in this family, but maybe this is just one created for fun - there's working versions of Forth out there in the world, and, y'know, spaceships.

Spaceships!

So say we all.

We really liked the side-by-side code'n'book (thanks James A for driving!). Let's make sure to do that in future.

Clone this wiki locally