-
Notifications
You must be signed in to change notification settings - Fork 15
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!
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!
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
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 scratchpad
namespace vocabulary.
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.
Some $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.
Simon: is 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 STDOUT
and STDERR
and then mutable globals $stdout
and $stderr
, which lets you temporarily reassign things and put them back after.
Q: Why?
A: Fun.
He mentions [
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?]
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 find
macro?
[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.
- Home
- Documentation
- Choosing a Topic
- Shows & Tells
- Miscellaneous
- Opt Art
- Reinforcement Learning: An Introduction
- 10 Technical Papers Every Programmer Should Read (At Least Twice)
- 7 More Languages in 7 Weeks
- Lua, Day 1: The Call to Adventure
- Lua, Day 2: Tables All the Way Down
- Lua, Day 3
- Factor, Day 1: Stack On, Stack Off
- Factor, Day 2: Painting the Fence
- Factor, Day 3: Balancing on a Boat
- Elm, Day 1: Handling the Basics
- Elm, Day 2: The Elm Architecture
- Elm, Day 3: The Elm Architecture
- Elixir, Day 1: Laying a Great Foundation
- Elixir, Day 2: Controlling Mutations
- Elixir, Day 3: Spawning and Respawning
- Julia, Day 1: Resistance Is Futile
- Julia, Day 2: Getting Assimilated
- Julia, Day 3: Become One With Julia
- Minikanren, Days 1-3
- Minikanren, Einstein's Puzzle
- Idris Days 1-2
- Types and Programming Languages
- Chapter 1: Introduction
- Chapter 2: Mathematical Preliminaries
- Chapter 3: Untyped Arithmetic Expressions
- Chapter 4: An ML Implementation of Arithmetic Expressions
- Chapter 5: The Untyped Lambda-Calculus
- Chapters 6 & 7: De Bruijn Indices and an ML Implementation of the Lambda-Calculus
- Chapter 8: Typed Arithmetic Expressions
- Chapter 9: The Simply-Typed Lambda Calculus
- Chapter 10: An ML Implementation of Simple Types
- Chapter 11: Simple Extensions
- Chapter 11 Redux: Simple Extensions
- Chapter 13: References
- Chapter 14: Exceptions
- Chapter 15: Subtyping – Part 1
- Chapter 15: Subtyping – Part 2
- Chapter 16: The Metatheory of Subtyping
- Chapter 16: Implementation
- Chapter 18: Case Study: Imperative Objects
- Chapter 19: Case Study: Featherweight Java
- The New Turing Omnibus
- Errata
- Chapter 11: Search Trees
- Chapter 8: Random Numbers
- Chapter 35: Sequential Sorting
- Chapter 58: Predicate Calculus
- Chapter 27: Perceptrons
- Chapter 9: Mathematical Research
- Chapter 16: Genetic Algorithms
- Chapter 37: Public Key Cryptography
- Chapter 6: Game Trees
- Chapter 5: Gödel's Theorem
- Chapter 34: Satisfiability (also featuring: Sentient)
- Chapter 44: Cellular Automata
- Chapter 47: Storing Images
- Chapter 12: Error-Correcting Codes
- Chapter 32: The Fast Fourier Transform
- Chapter 36: Neural Networks That Learn
- Chapter 41: NP-Completeness
- Chapter 55: Iteration and Recursion
- Chapter 19: Computer Vision
- Chapter 61: Searching Strings
- Chapter 66: Church's Thesis
- Chapter 52: Text Compression
- Chapter 22: Minimum spanning tree
- Chapter 64: Logic Programming
- Chapter 60: Computer Viruses
- Show & Tell
- Elements of Computing Systems
- Archived pages