billba / prague Goto Github PK
View Code? Open in Web Editor NEWFP helpers for games and chatbots
FP helpers for games and chatbots
Prague is meant to work both in browsers and in Node apps. But browsers and Node have very different runtimes. Browsers have XmlHttpRequest
and (increasingly) fetch
. Node has HTTP
.
Of course, per the "bring your own everything" philosophy of Prague, developers can use whatever they want in coding their bots. But at the very least our LUIS library will have to make some kind of call, and I can imagine adding libraries for other services e.g. cognitive services, Azure Search.
Also it would be nice to make it easy for them to build isomorphic (runs on either browser or server) bots out of the box, where by "out of there box" I mean "in the appropriate recipes".
At the moment we use RxJS' built-in get/post/etc. but they all sit on top of XHR. There are Node polyfills for XHR, but they are not comprehensive. And I don't think our recipes should require that developers use Observables for anything. It's great that they're available for those who want them, but let's keep the learning curve as shallow as possible.
My inclination is to use fetch
and add a fetch
polyfill for node applications. Opinions?
Code (in sample):
const fullName = first(
(t: string) => t === "Bill" && "Bill Barnes", // line 2
t => t === "Hao" && "Hao Luo",
t => t === "Kevin" && "Kevin Leung",
);
fullName("Bill").subscribe(console.log); // Match{ value: "Bill Barnes" }
fullName("Hao").subscribe(console.log); // Match{ value: "Hao Luo" }
fullName("Yomi").subscribe(console.log); // undefined
Actual:
Match { score: 1, value: 'Bill Barnes' } // correct
Match { score: 1, value: false } // unexpected
Match { score: 1, value: false } // unexpected
When "Bill" argument is commented out (line 2), results are:
Match { score: 1, value: false }
Match { score: 1, value: 'Hao Luo' }
Match { score: 1, value: false }
If a fall through behavior is correct, samples are wrong.
As in the alarm bot sample, I built a dialog to collect some basic information about stocks to be added to a portfolio. I'm basically prompting for tickerSymbol and quantity if I don't have them. My bot collects the ticker symbol and then asks the user for quantity (which I'm currently treating as a string). The issue is that the quantity response (e.g. "50") then gets set as the ticker symbol, and the bot gets stuck in a loop (see screenshot below).
router: (dialog) => first(
dialog.routeTo(textPrompt, _ => !dialog.state.tickerSymbol && { prompt: "What stock would you like to add to your portfolio?" }, m => {
if (validateStockName(m.dialogResponse.text, m))
dialog.state.tickerSymbol = m.dialogResponse.text;
return reroute(m);
}),
dialog.routeTo(textPrompt, _ => !dialog.state.quantity && { prompt: `What quantity of ${dialog.state.tickerSymbol} would you like to add to your portfolio?` }, m => {
dialog.state.quantity = m.dialogResponse.text;
return reroute(m);
}),
It seems like activating the second text prompt is effectively activating the first, which takes precedence in order.
Consider this:
first(
rule(matchRegExp(/I am (.*)/), match => match.reply(`hi, ${match.groups[1]}`)),
...
);
What type is match
? All we really know is that it's the input type to matchRegExp
plus IRegExpMatch
, which is to say that matchRegExp
adds groups
to the input type. But as to the overall type, and thus e.g. the type of match.reply
, we've got nothing, because we don't specify the input type to rule
. Which, by the way, is the answer for now:
first<YourTypeHere>(
rule<YourTypeHere>(matchRegExp(/I am (.*)/), match => match.reply(`hi, ${match.groups[1]}`)),
...
);
There are two things we'd like to be able to do here to make things more concise. The first is to be able to infer the type of rule by setting it in the enclosing first
:
first<YourTypeHere>(
rule(matchRegExp(/I am (.*)/), match => match.reply(`hi, ${match.groups[1]}`)), // type is not named, so infer it to be YourTypeHere
...
);
That this does not work is TypeScript issue #15680.
The other is to create typed shorthands for the helpers:
const f = first<YourTypeHere>, r = rule<YourTypeHere>;
f(
r(matchRegExp(/I am (.*)/), match => match.reply(`hi, ${match.groups[1]}`)),
....
);
That this does not work is TypeScript issue #15877
Until one or both of these suggestions is implemented, we're just going to be a little less concise than I would prefer if you want typing, which I do.
If you leave it out then match will always be any
, which is no worse than working in plain old JavaScript...
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.