Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
7ML7W Factor Day 2 Painting the Fence
Muffled introductions take place, muffled due to the presence of extremely tasty bread being extremely thoroughly consumed. Thanks Charlie!
What do we want to talk about?
We conclude we want to do the exercises together mainly, with James A's expert REPLing
Symbols - these are new and vaguely variable-esque. What do we think about these?
Tom: I didn't see the point of the stack effect stuff. What do the input and output names get used for?
James A: I think it said "they don't matter"
Mudge: These come into the exercises, but aren't really explained in the chapter. Let's find out!
The chapter then
We finally get to files, and tests, and other programmingy things.
These takes the form
: word-name stack-effect implementation ;
Tom: Why do these things need to declare arity, when quotations don't? Quotations are pretty much anonymous functions, so what's the deal?
Our example is adding 42 to the nearest value on the stack
IN: scratchpad : add-42 ( x -- y ) 42 + ; IN: scratchpad 123 add-42 . 165
You seem to be able to use anything as identifiers in the stack effect:
IN: scratchpad : add-43 ( 1 -- 2 ) 43 + ; IN: scratchpad 123 add-43 166
But it is checking arity:
IN: scratchpad : add-44 ( x y -- z ) 44 + ; :errors - show 1 compiler errors IN: scratchpad :errors ==== <Listener input> <Listener input> Asset: add-44 Stack effect declaration is wrong inferred ( x -- x ) declared ( x y -- z ) :errors - show 1 compiler errors
James A: in the GUI app at least you can define a word and its documentation from the stack effect is dynamically added to the system's live docs, which is nice
Returning multiple values
You can easily say "this will put two things on the stack:
: push-1-2 ( -- x y ) 1 2 ; push-1-2 --- Data stack: 1 2
Appropriately enough I lost the thread here. Something about backslashes and sequences and accessing docs. We have no idea what we're doing and generate a bunch of weird errors by trying to get help for the word that matches the last identifier on the stack? I think?
Akin to namespaces - e.g. in our repl we always see
IN: scratchpad, cos we're defining stuff in the
We learn about "restarts" via the helpful messages you get when you don't have the right vocabulary loaded:
1: number>string ^ No word named “number>string” found in current vocabulary search path The following restarts are available: :1 Use the math.parser vocabulary :2 Defer word in current vocabulary Type :help for debugging help. IN: scratchpad :1 1: Note: Added "math.parser" vocabulary to search path Data stack underflow
Leo: They seem like globals, right?
Yeah, a bit.
Tom: I was really surprised by this - all this faffing around with the stack and you can just, like, stuff things into globals?
James C: are these just a convenience, or computationally essential to reach turing completeness?
Tom: I'd assume that because one of the things you can push on the stack is arbitrary code, that should be enough. There's not much motivation for them in the book, so I would guess they're a convenience?
Mark: I was kinda disappointed by this to be honest.
Mumbles of "boo, sellout" (aimed at factor, not Mark, to be clear)
Tom: It's probably pragmatism, isn't it.
[mumbled suggestions that we like our side project languages ideologically pure]
Tom: you could think about this a bit like a stack-based CPU, where the CPU is still working with stacks, and still have system memory somewhere that your stack instructions can access?
James C: in hard real-time systems you tend not to have, say, garbage collection, because it can introduce unpredictable pauses. So maybe there's a case here to say it's good to have some sort of statically declared global state that's fixed? But OTOH these names can refer to arbitrary and changeable values, so you'd still have the GC problem. Hmm.
$FACTOR_ROOTS discussion. Is it like
$GOPATH or is it more like the java classpath? It's probably more like the latter, particularly given factor's JVM heritage. James A has already set his up.
Mudge: so there's lots of examples, and they're all intentionally broken, hurrah.
We tackle writing a greeter vocabulary - despite our
$FACTOR_ROOTS we get an error referring to
swap, because in standalone files we don't get everything loaded for us by default, just a massive unhelpful stacktrace. So we need our program to be:
USING: kernel sequences ; IN: examples.greeter : greeting ( name -- greeting ) "Hello, " swap append ;
USING: examples.greeter io ; IN examples.hello : hello ( -- ) "world" greeting print ;
$ factor examples/hello.factor Hello, world
Dmitry: can we use fully-qualified names without inputs?
We don't know.
A bit of chat about whether it's good to have pedantically enumerated explicit imports vs a bunch of things conveniently available or not, and as you can imagine we arrived at a single, conclusive answer, which was that [unintelligible].
You have to be hella precise with your naming or it just gets ignored here. Conventions eh!
Tom: A convention with which you MUST comply
We run a test and see some glorious output, in particular some glorious failures.
[At this point we read through the test runner example line-by-line]
HMM not sure:
So the interesting thing here seems to be that this runner seems to stick its results in a symbol which you can access later (c.f. compiler
:errors. And indeed we've got some convenience word
:test-failures which isn't the symbol called the same thing, but instead pretty-prints your failures.
with-null-writer also using symbols to define what the IO streams are?
Mudge: Maybe? It's definitely using some sort of global state for streams. I think we see this later.
Tom: I think it might be a bit rubyish - you've got constants
STDERR and then mutable globals
$stderr, which lets you temporarily reassign things and put them back after.
Interview with Slava Pestov
[ being a word, which knowledge we combine with our newfound docs expertise:
IN: scratchpad \ [ help [ Factor documentation > Factor handbook > The language > Syntax > Literals > Quotation syntax Next: ] ( -- * ) Vocabulary syntax Syntax [ elements... ] Word description Marks the beginning of a literal quotation. Examples [ 1 2 3 ] See also ] Definition USING: parser sequences ; IN: syntax SYNTAX: [ parse-quotation suffix! ;
That's a pretty cool stack effect too -
* for variadic output?
James A: Hey, look at that
SYNTAX: declaration. I bet we can do one of those!
[James proves this by defining syntax
% that prints the word "wibble"? I think?]
Some random chat about producing native executables
We agree that this is good. Is it portable though?
We could run
deploy-tool, if only we could find it. Is it an executable? A word? A fish? A loaf? WHO KNOWS.
Googling doesn't help. Is this a totally ungooglable language?
James A: So much R stuff comes up. Which is ironic, as R is itself totally ungooglable.
[We work it out - you do it at the repl probably, or in your own build program. I miss the correct incantation.]
[10 minutes pass]
[It turns out the compile failed and we've uncovered a bug in factor? Maybe? As long as it fails on multiple CPU architectures it's still portable, though, which is the main thing.]
We run into LOTS of trouble trying to implement the
find-first exercise using
find. But we get a super-weird operator about inline words out of this, and looking at the docs for
find we see that it's a macro?
Mudge: so I think this is kinda what we're seeing here is that the
find macro is using its stack effects to try to check that the arguments you're providing it match what it expects. We can short-circuit this with
inline but that's really like cheating.
James C: is this really the point of this exercise, or is there actually a way to write a loop over a sequence in factor?
We're not sure.
Tom: can we also make this pass by using the right incantations in the stack effect for our own
find-first word? I.e. by replicating the nested stack effects of the
[we try this, and no, same error]
Mudge: Okay but we can by doing [unintelligible]
[Something happened here. It involved curry, nested quotations,
call( and quite possibly magical beans.]
James C: This is unreasonable.
find is a really simple combinator.
Joel: I fixed this with
inline, but I didn't really understand what
inline does so I put it first, and it just worked.
[we verify that it totally does]
It seems like none of us know what
inline does and we don't know where we would've been expected to find this out. Bleh.
Mark: It declares the most recently-defined word as an inline word.
All: OKAY so that's why it didn't matter where it goes.
After ~10 minutes of mobbing the solution to numberguess an actual angry mob turns up and we are forced at pitchfork-point to convene a swift...
Charlie volunteers to organise the next meeting! Thanks Charlie.
At this we run off because we've run over. Some delayed retrospective action's going on in the book channel on slack, which might get transcribed here later.