Tau-Prolog Interpreter shows different behaviour than SWI-Prolog - javascript

I'm currently trying to implement some basic Prolog queries in Tau-Prolog. Although I have working queries in SWI-Prolog, I can't implement them to work in Tau-Prolog.
I would like to return the name of all Robots that are in the database and have the Interface "B".
Is there something important I am missing here? I think that sub_string/5 might be the reason why it's not working. It also won't work when I paste the Code into the trial interpreter on http://tau-prolog.org/
Does anyone know a way to fix this query so it could work in Tau-Prolog? Thanks in advance!
<script>
var session = pl.create(1000)
var database = `
robot('Roboter1','A', 1, 550).
robot('Roboter2','C', 2, 340).
robot('Roboter3','B', 2, 430).
robot('Roboter4','A', 2, 200).
robot('Roboter5','B', 3, 260).
`
function start_query_RwB(){
query_RwB();
}
function query_RwB(){
var queryRwB = "queryRwB :-write('Interface B has: '),robot(Name, Interface,_,_),sub_string(Interface,_,_,_,'B'),write(Name),nl, fail."
var code_pl = database.concat(queryRwB);
var parsed = session.consult(code_pl)
var query = session.query('queryRwB.')
function inform(msg) {
show_result4.innerHTML += msg
}
session.current_output.stream.put = inform;
var callback = function(answer) {
}
session.answer(callback);
}
</script>

Use sub_atom/5 instead of sub_string/5 in the definition of the queryRwB variable as you use atoms, not strings, in the definition of the predicate robot/4:
var queryRwB = "queryRwB :-write('Interface B has: '),robot(Name, Interface,_,_), sub_atom(Interface,_,_,_,'B'),write(Name),nl, fail."
Note that sub_atom/5 is a standard predicate (that's implemented by Tau Prolog) while sub_string/5 is a proprietary predicate only found in some Prolog systems like ECLiPSe and SWI-Prolog.

Related

Adding 3 drop down text values in jscalc.io

I created a simple calc with jscalc.io and I'm having trouble parsing values so I can add them.
I have played with a few variations of the following code but no luck. My javascript knowledge is really limited, like this is the first time writing something in JS. :)
jscalc.io returned the following error for this code:TypeError: null is not an object (evaluating 'inputs.Age.value')
"'use strict';
var varAge = parseFloat(inputs.Age.value);
var varWeight = parseFloat(inputs.Weight.value);
var varGender = parseFloat(inputs.Gender.value);
return {
total: varAge + varWeight + varGender
};
Any help would be much appreciated, thanks!
Just going to preface this by saying that I've never used jscalc.io, but I looked at the example and it looks like you're supposed to use inputs.Age instead of inputs.Age.value. Also, if you make your inputs as Numbers, you don't need to use parseFloat. So your fixed code would look like this:
'use strict';
var varAge = inputs.Age;
var varWeight = inputs.Weight;
var varGender = inputs.Gender;
return {
total: varAge + varWeight + varGender
};

What external context could cause splice to not do anything?

I have this splice line, with a debug line either side:
const obj = { x:[1,2], y:{t:"!!!"} }
const lenBefore = S.groupings.length
const ret = S.groupings.splice(gix, 0, obj)
console.log(`${lenBefore} --> ${S.groupings.length}, gix=${gix}, ret=${JSON.stringify(ret)}`)
It gives this output, which I believe is impossible:
3 --> 3, gix=2, ret=[]
I.e. the splice did not add or remove anything.
Another run, on different data, gave:
18 --> 18, gix=2, ret=[]
This function is fairly complex, but I have some unit tests to cover the main ways it is used. I left the console.log() lines in when running them, and those tests give me:
1 --> 2, gix=0, ret=[]
3 --> 4, gix=1, ret=[]
I.e. exactly what I'd expect. So, something about the environment when run for real is causing this.
(It is an electron app, this code is running in the front-end part, i.e. effectively in Chrome, and it is with Chrome developer tools that I'm looking at the console. The unit tests are running in mocha 3.2.0, node 6.11.4. The real environment is Electron 1.8.1, which is Chrome 59, i.e. slightly newer.)
Has anyone any idea what external context could possibly cause splice() to not do its job?
UPDATE:
If I instead use this, then everything works both in the live code and in the unit tests:
S.groupings = S.groupings.slice(0,gix).concat(obj, S.groupings.slice(gix))
There is obviously something about S.groupings that stops it being mutated, but just in my complex live code, not in a unit test! That in itself is quite interesting, as I thought it was not possible to make immutable javascript objects...
BTW, the following code:
console.log(`S type=${typeof S}; isArray=`+ Array.isArray(S))
console.log(`S.groupings type=${typeof S.groupings}; isArray=`+ Array.isArray(S.groupings))
tells me identical results in live and unit test code:
S type=object; isArray=false
S.groupings type=object; isArray=true
And I also tried this, near the top of the function:
S.groupings = Array.from(S.groupings)
It made no difference. I.e. all the evidence points to that S.groupings is just a normal JavaScript array.
UPDATE 2: Not frozen or sealed:
Object.isFrozen(S.groupings) //false
Object.isSealed(S.groupings) //false
Object.isExtensible(S.groupings) //true
By the way, to try to narrow it down I made the following three, increasingly complex, simplifications of the real code, as mocha tests. They all pass perfectly. Of course they do. I decided to include it here, as it gives you more context than the one line I posted above, and also shows some things that are obviously not the explanation.
it("1", function(){
const S = {
groupings:[ {a:1,b:2}, {a:2,b:"xxx"}, {a:3,b:false} ],
tom:"hello",
dick:[1,2,3],
harry:null
}
const obj = {a:2.5, b:"INSERT ME"}
let gix = 2
assert.equal(S.groupings.length, 3)
S.groupings.splice(gix, 0, obj)
assert.equal(S.groupings.length, 4)
})
//--------------------------------
it("2", function(){
const S = {
groupings:[ {a:1,b:2}, {a:2,b:"xxx"}, {a:3,b:false} ],
tom:"hello",
dick:[1,2,3],
harry:null
}
const CG = [ {z:1}, {z:2}, {z:3} ]
const obj = {a:2.5, b:"INSERT ME"}
for(let gix = 0;gix < CG.length; ++gix){
const g = CG[gix]
if(g.z < obj.a)continue
assert.equal(S.groupings.length, 3)
S.groupings.splice(gix, 0, obj)
assert.equal(S.groupings.length, 4)
break
}
})
//--------------------------------
it("3", function(){
const data = {
"1":{},
"2":{
groupings:[ {a:1,b:2}, {a:2,b:"xxx"}, {a:3,b:false} ],
tom:"hello",
dick:[1,2,3],
harry:null
}}
const CG_outer = [ {z:1}, {z:2}, {z:3} ]
function inner(CG, txt){
const S = data["2"]
const obj = {a:2.5, b:txt}
for(let gix = 0;gix < CG.length; ++gix){
const g = CG[gix]
if(g.z < obj.a)continue
assert.equal(S.groupings.length, 3)
S.groupings.splice(gix, 0, obj)
assert.equal(S.groupings.length, 4)
break
}
}
inner(CG_outer, "INSERT ME")
assert.deepEqual(data["2"].groupings,
[ {a:1,b:2}, {a:2,b:"xxx"}, {a:2.5, b:"INSERT ME"}, {a:3,b:false} ] )
})
I've finally tracked it down. Electron apps have distinct back-end/front-end processes, with message parsing. I was doing this:
S = mainProcess.getLatestData(...)
If I change that to:
const ret = mainProcess.getLatestData(...)
Object.assign(S, ret)
then everything, including splice() works as expected.
I cannot really explain what is going on, though. ret is not frozen, sealed, and is extensible. It appears to be a plain JS object in all respects, and ret.groupings to be a simple JS array.
And S was originally data that came from the front-end. (However that was sent in an event from the front-end, rather than requested, and those are two different mechanisms in Electron.)

setting object through variable containing strings not working

I have developed a pretty basic audio player on on my website similar to SoundClouds.
I have managed to successfully finish it, and I am starting to clean up all the markup, including (trying) removing all inline event handlers (i.e: onclick="" or onkeyup="").
However, I have come across a bit of a problem in my JavaScript whilst doing this.
It's a bit hard to explain so I'm going to post my JavaScript, then give you an idea of what the problem is:
$(".track-w__trigger").click(function(){
var tid = $(this).attr('aria-trackid'); // aria-trackid is equal to a random integer created by PHP
var tiW = 'w' + tid + 'w'; // this is an object (i.e: w3w)
playPauseButton(this, tiW, ti);
});
function playPauseButton(button, wave, trackID){
var button = $(button);
if(wave.isPlaying()){ // the object (w3w.isPlaying())
button.removeClass("playing");
wave.pause();
} else {
button.addClass("playing");
wave.play();
}
}
What I used to have was
<div class="track-w__trigger" onclick="playPauseButton(this, w3w, 3)" id="w3w-trigger"></div>
and now it is:
<div class="track-w__trigger" aria-trackid="3" id="w3w-trigger"></div>
As you can see in the second block of code. w3w is an object. However, because I have set it using my click function in a separate script using string quotes. JavaScript has gone ahead and made it a string.
So now when I use wave.isPlaying() for example; it does nothing.
I have no idea how to fix this, and no result on Google will help me. Any help in fixing this issue would be greatly appreciated,
Thanks!
EDIT:
This is where & how w3w is set:
var w3w = Uki.start({
// e.t.c
});
Use eval
wave = eval(wave);
to evaluate the string as a function
or use a safer way
wave = window[wave];
https://jsfiddle.net/zmr412q7/
Instead of having each object as a seperate variable, create an object that contains each object at the id representing the N in wNw. Ex:
var wNw = {};
// represents w1w
wNw[1] = (Uki.start({
// e.t.c
}));
// represents w17w
wNw[17] = (Uki.start({
// e.t.c
}));
// represents w3w
wNw[3] = (Uki.start({
// e.t.c
}));
This gives you an object that looks like:
{
1: object_that_was_w1w
17: object_that_was_w17w
3: object_that_was_w13w
}
And then your click handler looks like this:
$(".track-w__trigger").click(function(){
var tid = $(this).attr('aria-trackid'); // aria-trackid is equal to an integer of 1 to 5
var tidNum = parseInt(tid);
playPauseButton(this, wNw[tidNum], ti);
});
You can try something like this,
var tid='w'+5+'w';
var tryout=tid.valueOf();
console.log("getting the object "+tryout)
The valueOf property converts the string to an object

js_of_ocaml and Deriving_Json

I need some help to get js_of_ocaml working. There's not much information about it on the net, and the manual is very sparse (no snippets or usage examples, no comment sections).
I have a Card module on the server with a card record. I'm sending a card list to the client using Ajax, and there I want to read and traverse this list. What I end up with is this:
let json = Json.unsafe_input (Js.string http_frame.XmlHttpRequest.content) in
...where json has type 'a, according to documentation (not when I run it, of course).
I can log json##length and get the correct length of the list. Where do I go from here? Ideally, I'd like to use Deriving_Json to type-safe get a card list again, but I could also use a for-loop (not as elegant, but whatever).
Type declarations like type name = ... deriving(Json) creates Json_name module.
Here is example.
type card = {a: int; b: string; } deriving(Json)
type t = card list deriving(Json)
let _ =
let str = Json.to_string<t> [{a = 10; b = "abc";}; {a = 20; b = "xyz";}] in
let rs = Json.from_string<t> str in
Firebug.console##log(Js.string str);
List.iter (fun r -> Firebug.console##log_2(r.a, Js.string r.b)) rs
And I'm not sure why, I got "Uncaught ReferenceError: unix_inet_addr_of_string is not defined".
So add function unix_inet_addr_of_string () {return 0;} to js file.

javascript multiline dict declaration

I'm having an issue. I want to have a static dict
var myDict={"aaa":true,"aab":false,"aac":false,"aad":true, [...] };
There are a lot of entries, and I want to have an easy access to all of them in case I need to change their value. Because of this, I don't like the single-line declaration.
As an alternative, I did manage to do the following, since multi-line text is allowed in Javascript:
var dict = {};
var loadDict = function() {
text = "aaa,true\n\
aab,false\n\
aac,false\n\
aad,true\n\[...]";
var words = text.split( "\n" );
for ( var i = 0; i < words.length; i++ ) {
var pair = words[i].split(",");
dict[ pair[0].trim() ] = pair[1].trim();
}
}
Is there a better/more elegant way of having a multi-line declaration of a dict?
note: Creating multiline strings in JavaScript is a solution only for strings. it doesn't work with a dict.
edit: I was adding a '\' at the end of each line. That was the issue. thanks.
var myDict = {
"aaa": true,
"aab": false,
"aac": false,
"aad": true,
[...]
};
I hope this is what you meant, because it's basic Javascript syntax.
Also, if for some reasons you want to "store" simple objects (made of strings, numbers, booleans, arrays or objects of the above entities) into strings, you can consider JSON:
var myDictJSON = '{\
"aaa": true,\
"aab": false,\
"aac": false,\
"aad": true,\
[...]
}';
var myDict = JSON.parse(myDictJSON);
Support for JSON is native for all the major browsers, including IE since version 8. For the others, there's this common library json2.js that does the trick.
You can also convert your simple objects into string using JSON.stringify.
that's easy-
var myDict={
"aaa":true,
"aab":false,
"aac":false,
"aad":true
};
please remember, don't place the curly bracket in the next line.
i like responses. Please respond
This (a complex data structure containing both "string" and "booleans"):
var myDict={"aaa":true,"aab":false,"aac":false,"aad":true, [...] };
Can be expressed like this:
var myDict={
"aaa":true,
"aab":false,
"aac":false,
"aad":true,
[...]
};
Similarly, this:
var myBigHairyString = "Supercalifragilsticexpialidocious";
Can be expressed like this:
var myBigHairyString =
"Super" +
"califragilstic" +
"expialidocious";

Categories