Comments (18)
That works for me.
Using this issue as a cross-repo tracker:
- - Add symbols to lucy-prism
- - Add symbols to lucy-vscode
- - Update docs to reflect preference for symbol usage and update compilation examples.
- - Add symbols in liblucy and make sure they work in: (PR: #41)
- - assign(prop, :load)
- - action(:log)
- - guard(:check)
- - delay(:dynamic)
- - invoke(:callback)
- - spawn(:machine)
- - action logger = :log
- - guard check = :check
- - Make invoke callable in liblucy
- - Pass context through the new exported fn
from liblucy.
@matthewp Very nice. I dig that :something
syntax, too. Very clear and should allow for nice autocomplete for duplicates.
One small change I would make is to change:
export default function(context, options) {}
to...
export default function(options) {}
Where context is a key on the 'options' object. This more closely matches current implementations, like useMachine
, and also covers spots where implementations are required but context is not. For instance, context-less machines like Tab Focus here:
https://xstate-catalogue.com/machines/tab-focus
from liblucy.
Thanks for raising this issue, I had thought about some sort of function export initially, I was thinking about it in terms of unimplemented actions/guards like you have mentioned. So I was concerned that there might need to be some type of export syntax and a way to define arguments. Now I see that we probably don't need that. Any unimplemented guard/action becomes part of the arguments.
There's probably a lot to discuss here, so. I want to think/talk about this more so we can break down the issue. I would say that the ultimate goal here is to allow completely implementation-free Lucy machine definitions.
Possibly even deprecating/removing implementation touch points like use
and inline actions/guards. Ergonomics is key here, as inline actions/guards were pretty ergonomic and we don't want to lose that by getting rid of them.
from liblucy.
Side-note, this would also fix the fact that you currently cannot define the initial context in Lucy (except clumsily through @entry
definitions in your initial state).
from liblucy.
Side-note, this would also fix the fact that you currently cannot define the initial context in Lucy (except clumsily through @entry definitions in your initial state).
Currently, you could do it via machine.withContext()
. But point taken, a function would be much more ergonomic.
use
is a really interesting API, because it allows for arbitrary code execution while still allowing the lucy schema to be statically extractable. But typing it might be more trouble than it's worth? Torn.
from liblucy.
I think where I'm landing on this issue is:
- Change exported machine defintions to be a function that creates the machine. This will make TypeScript easier (future issue).
- Use a convention of
create[MachineName]
as the exported function name. Single machine Lucy files will continue to export default. - Add new syntax:
:name
to signal an external value provided by initialization.
use
and referencing imported JS will remain in, for now. We can omit showing that in the docs, and assuming all goes well we can deprecate and remove in the future.
Other things discussed in this issue (such as special syntax for data properties) will be done in a future issue.
Example payment machine:
initial state idle {
purchase => purchasing
}
state purchasing {
=> guard(:fundsAvailable) => action(:logTransaction) => purchased
}
final state purchased {}
Would produce:
import { createMachine } from 'xstate';
export default function(context, options) {
return createMachine({
initial: 'idle',
context,
states: {
idle: {
on: {
purchase: 'purchasing'
}
},
purchasing: {
always: [
{
target: 'purchased',
cond: 'fundsAvailable',
actions: ['logTransaction']
}
]
},
purchased: {
type: 'final'
}
}
}, {
...options
});
}
from liblucy.
@mattpocock You mentioned passing context
through as part of the options. I think that will mean the signature will look something like this:
export default function({ actions, assigns, context, delays, guards, services }) {
return createMachine({
context,
// ...
});
}
My TS skills are a little weak, will we be able to type context
here using generics?
function createToggleMachine<T>({ actions, context }: { actions: SomeType, context: T }) {
Is that valid? Would it be valid if the options type here was moved up into an interface as well?
interface CreateToggleMachineOptions<T> {
actions: SomeType;
context: T;
}
function createToggleMachine<T>({ actions, context }: CreateToggleMachineOptions<T>) {
from liblucy.
This is close to being ready implementation wise. Biggest issue at the moment is what to do when invoking/spawning submachines. How are the child machines going to get their options dependencies? Currently I think we are going to have to say that child machines can't have options deps and we'll just call the createChildMachine()
function to get the StateMachine instance. Down the line we'll need a solution for this though.
from liblucy.
Code is implemented. All is left is updating docs. PR is here: #41
If anyone wants to review, this is the test to look at:
- Input: https://github.com/lucydsl/liblucy/blob/0de0bf894eccda870761380e2e8a06d0471deea6/test/snapshots/symbols/input.lucy
- Output: https://github.com/lucydsl/liblucy/blob/0de0bf894eccda870761380e2e8a06d0471deea6/test/snapshots/symbols/expected.js
Does this match everyone's expectations? What I like about this is that you can use symbols anywhere, in spawn(), in invoke(), not just action/guard.
from liblucy.
Some things we need to figure out:
- What named invokes look like.
- The naming convention for exported machine functions (ex. does
ToggleMachine
becomecreateToggleMachine
? Is that intuitive for the user?)- I've also wanted it to be possible to have machine definitions that are not exported. How does that work?
- What the arguments should be.
- If there's a more ergonomic way to define named actions/guards than the current form.
from liblucy.
https://www.loom.com/share/8f652e019a9b4eada5ca9662b13cec8e
from liblucy.
Nice! Yeah we might be able to just change all of these to function-call style, where the argument is actually the name. Something to think more about, want to look at other DSLs for inspiration here as well.
By non-exported machine definitions I mean something like this:
machine uploadMachine {
// ...
}
machine MainMachine {
state startup {
invoke uploadMachine {
done => idle
}
}
state idle {}
}
uploadMachine
is used internally only. Currently it will be exported though. Ideally we would only export the machines intended to be interpreted. In Go the first letter determines if it is exported; if it starts with a capital letter it is, if it starts with a lowercase it is not. Possible we could use that convention too. I'd prefer avoiding export
keyword if possible (don't think DSLs typically have such a concept).
from liblucy.
Types of references in Lucy:
- Identifiers - References to variables inside file
- Data - Context properties (idea -> @todo)
- Implementation names - Named actions/guards/delays, etc. (idea -> :canProceed)
- Event names - Names of events
https://www.loom.com/share/2d4297e26e014f22ac218a8faa0a4b23
cc @mattpocock
from liblucy.
@matthewp Nice!
Agree with everything in here. One thing to note is a fifth kind of 'thing' in Lucy - spawned actors in context. In send(firstArg, secondArg)
, the firstArg is presumably the actor you're targeting? I.e a reference to that actor. So you have references to static definitions, and also references to items in context.
An interesting idea is how much specific actor co-ordination/spawning we want to do within Lucy itself - technically actor spawning is all implementation detail! Since it all lives within context/actions etc.
Also 100% agree that Lucy should be independent from XState. XState is a compile target, and Lucy may end up wanting to support different compile targets. That means that we should really be supporting a subset of what is possible in XState, not looking for feature-completeness.
from liblucy.
Spawned actors are saved as properties on the context (ie, data), so they are data like anything else that gets assigned. When you send a message to an actor you are sending it to that context property, so send(@actorName, eventName)
is correct I think. By allowing Lucy to know about the data in a machine we can statically verify that actorName
is indeed an actor and not some other type of data.
from liblucy.
One thing that faintly worries me is that if you allow 2+ machines inside a file, eventually folks will ask you for modularity, and import/export syntax. Especially when you could conceivably build very complex actor systems out of this. Not necessarily a danger, but something to bear in mind.
from liblucy.
@matthewp Yes, exactly! Here is the exact type signature you need:
from liblucy.
Closed by #41
from liblucy.
Related Issues (20)
- Allow comments HOT 1
- Allow for stopping spawned actors HOT 5
- Guards for immediate transitions HOT 1
- Allow for unimplemented actions/services/guards HOT 13
- Add option for outputting to JSON HOT 4
- Add node/browser lib for Lucy HOT 2
- Incorrect indentation when a reference follows an inline assign
- Named actions/guards get shared with sibling machines
- [IDEA] XState JSON to Lucy? HOT 8
- Parallel states
- Nested states without nested machines HOT 2
- Compile hangs if too many repeated event definitions HOT 1
- Actions in nested machines HOT 2
- Target a nested state with an event HOT 2
- spawning should be done with a callback
- dts not created for entry actions
- Sending to an actor should include parent event data
- Invoking "use reference" is incorrectly referenced in services property HOT 2
- Why not javascript? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from liblucy.