Code:
[mia, vincent, jules, yolanda].
[mia, [vincent, jules], [butch, girlfriend(butch)]].
% uncommenting the below line gives an error:
% [mia, vincent, X].
According to my book and different sites on the internet, it's perfectly fine to include variables in prolog lists yet on loading the above knowledge base I get the following error:
ERROR: /home/user/Prolog/det/lists.pl:7:
Arguments are not sufficiently instantiated
ERROR: /home/user/Prolog/det/lists.pl:7:
Arguments are not sufficiently instantiated
In:
Arguments are not sufficiently instantiated
Arguments are not sufficiently instantiated
In:
[31] throw(error(instantiation_error,_4850))
[27] '$load_file'('/home/user/Prolog/det/lists.pl','/home/user/Prolog/det/lists.pl',_4878,[expand(false),...]) at /usr/lib/swi-prolog/boot/init.pl:2507
[26] setup_call_catcher_cleanup(system:true,system:'$load_file'('/home/user/Prolog/det/lists.pl','/home/user/Prolog/lab4/lists.pl',_4946,...),_4924,system:'$end_consult'(...,user)) at /usr/lib/swi-prolog/boot/init.pl:443
[22] '$do_load_file_2'(lists,'/home/user/Prolog/lab4/lists.pl',user,compiled,[expand(false),...]) at /usr/lib/swi-prolog/boot/init.pl:2124
[19] '$mt_do_load'(<clause>(0x55a555ed3400),lists,'/home/user/Prolog/lab4/lists.pl',user,[expand(false),...]) at /usr/lib/swi-prolog/boot/init.pl:2070
[18] setup_call_catcher_cleanup(system:with_mutex('$load_file',...),system:'$mt_do_load'(<clause>(0x55a555ed3400),lists,'/home/user/Prolog/det/lists.pl',user,...),_5084,system:'$mt_end_load'(<clause>(0x55a555ed3400))) at /usr/lib/swi-prolog/boot/init.pl:443
[7] <user>
It certainly is fine to include variables in lists, but the lists need to be put in a context.
Just writing [mia, vincent, jules, yolanda]. is actually a shortcut to load files, as in consult/1.
You have to use those lists as the argument of a term for example:
list_of_people([mia, vincent, jules, yolanda]).
Maybe better written
person(mia).
person(vincent).
person(jules).
person(yolanda).
and then collected
?- bagof(P,person(P),PersonList).
PersonList = [mia,vincent,jules,yolanda].
Related
i have a function that takes 3 arguments
(defn times-changed-answer [rid qid csv-file] ...some code)
that counts for a user with (record-id) rid how many times he changed his answer with (question-code) qid. The data is in csv-file.
It works and i have tested it for multiple users.
Now i want to call this function for all users and for all questions.
I have a list of rids and a list of qids.
(def rid-list '(1 2 4 5 10)
(def qid-list '(166 167 168 169 180 141)
How could i call this function on all users for all questions?
The lists are of different length and the third argument (the file) is always the same.
I'd use for list comprehension - it depends on what result you expect
here; here e.g. [rid qid result] is returned for all of them:
(for [rid rid-list
qid qid-list]
[rid qid (times-changed-answer rid quid csv-file)])
If you want to have this in a map, you could e.g. reduce over that.
I have following data in text file I read from stdin:
4.5 12 -16
12 37 -43
-1.6 -4.3 98
1
2
3.3
I execute some basic parsing on it and get to a (wanted) point where I have it parsed to structure as follows:
[[[4,.,5],[1,2],[-,1,6]],[[1,2],[3,7],[-,4,3]],[[-,1,.,6],[-,4,.,3],[9,8]],[[]],[[1]],[[2]],[[3,.,3],[]]]
Which basically is a list of lines, where lines are also lists of numbers represented as list of chars. Now I would like to convert it to list of lines, where line would be a list of numbers - mixed list of both float and integer values. So my questions: Is mixed list even possible in Prolog? And how would I convert string to either integer or float based on presence of 'dot'?
I tried using plain atom_string(X, [1,.,5]).to test whether this is the way, but it ends up with Arguments are not sufficiently instantiated (which I somehow don't understand, when both of the arguments should be of '?' type which would mean that they can be both input and output variables.
I cannot guess which Prolog you are using, but in case you are using SWI-Prolog, there is a nice little library, library(dcg/basics). It is a bit difficult to find, but it has DCG primitives for parsing that make this a very easy task. If you are not using SWI-Prolog you could just copy the library, or use the definitions that it has in your code (make sure to read the license!).
So here is the solution in SWI-Prolog:
:- use_module(library(dcg/basics)).
input_to_numbers(Input, Numbers) :-
phrase_from_stream(numbers(Numbers), Input).
numbers([]) --> eos, !.
numbers([Ns|Rest]) -->
nums_line(Ns), !,
numbers(Rest).
nums_line([N|Ns]) -->
whites,
number(N), !,
nums_line(Ns).
nums_line([]) --> blanks_to_nl.
It uses the following DCGs from the library: eos//0, whites//0, number//1, and blanks_to_nl//0. Note that number//1 can read either an integer or a float, and also reads floats written as 1.7e3 for example.
This particular implementation insists to read every line, and for lines without numbers it will give you an empty list. It can only return an empty list if the input is completely empty! It will fail if there is any non-number in your input. But once you have the primitives it is easy to adjust to your needs.
This is the complete code, you just need to feed your example file somehow to it. If you want to do it from "standard input", you would use user_input as the input stream:
?- input_to_numbers(user_input, Ns).
|: 4.5 12 -16
|: 12 37 -43
|: -1.6 -4.3 98
|:
|: 1
|: 2
|: 3.3
Ns = [[4.5, 12, -16], [12, 37, -43], [-1.6, -4.3, 98], [], [1], [2], [3.3]].
So I called this from the top level and just pasted the contents and typed Ctrl-D to put end-of-file. If you had your input in a file, you could instead do:
?- setup_call_cleanup(open('nums.txt', read, In),
input_to_numbers(In, Ns),
close(In)).
In = <stream>(0x19a6740),
Ns = [[4.5, 12, -16], [12, 37, -43], [-1.6, -4.3, 98], [], [1], [2], [3.3]].
Just in case you still need to parse numbers using comma as decimal separator, here is a simple way (replace number//1 with number_//1 in the DCG Boris has posted):
number_(Number) -->
( integer(Int), ",", integer(Frac)
-> {format(codes(Cs), '~d.~d', [Int, Frac]), number_codes(Number, Cs)}
; number(Number)
).
It shows how flexible the DCG notation can be...
This question already has answers here:
"Least Astonishment" and the Mutable Default Argument
(33 answers)
Closed 6 years ago.
In the code below, I am expecting that a new instance of MyClass with the name 'obj' will be created every time inside the for loop. Therefore, the output should be [1] every time. But obj.mylist seems to grow. What am I missing?
class MyClass:
def __init__( self, mylist_=[] ):
self.mylist = mylist_
def addData( self ):
self.mylist.append( 1 )
for i in range(5):
obj = MyClass()
obj.addData()
print obj.mylist
The output is:
[1]
[1, 1]
[1, 1, 1]
[1, 1, 1, 1]
[1, 1, 1, 1, 1]
Long story short, default values for arguments are created once at the time that the statement that defines the function is executed.
Please refer to the official documentation:
The default values are evaluated at the point of function definition in the defining scope, so that…
<…>
Important warning: The default value is evaluated only once. This makes a difference when the default is a mutable object such as a list, dictionary, or instances of most classes.
<…>
— 4.7.1. Default Argument Values — Python 3.5.2 documentation.
This reference also contains the example of not following the warning — a very similar case and observed behavior.
Additional references:
Using a mutable default value as an argument: Anti-pattern.
Not a bug: Issue 448911: Empty list as default argument problem - Python tracker.
Common Gotchas: Mutable Default Arguments — The Hitchhiker's Guide to Python.
Python insight: beware of mutable default values for arguments - Eli Bendersky's website.
Gotcha — Mutable default arguments | Python Conquers The Universe.
Let me try to put this in a simple manner.
I have 2 lists, which look like below:
List1 = [('a', 1, 'low'), ('b', 10, 'high')] # --> Tuples in List
List2 = ["('a', 1, 'low')", "('b', 10, 'high')"] # --> Here the Tuples are actually of Type String.
List1 is output of a SQL query. List2 is defined by me as expected result.
I am using Robot Framework to compare these two lists with the Keyword Lists Should Be Equal. But it fails as List2 has strings which look like Tuple.
How can I compare these two lists? Can I convert both the lists to a different variable type so that I can compare them. I am trying to avoid the python coding here.
It's unclear exactly what your data looks like, but since the two lists have different contents you'll have to convert one or both of them to a common format.
You could, for example, convert the first list to a string with something like this:
| ${actual}= | Evaluate | [str(x) for x in ${List1}]
I doubt that gives you exactly what you need because, again, it's unclear exactly what you need. However, the technique remains the same: use Evaluate to write a little bit of python code to convert one of your lists to be the same format as the other list before doing the compare.
This may be the long procedure, i have used tuples (1,2) instead (a,1,low) #( cause name error in python). But you told its getting from SQL. Important is difference between (1,2) and (1, 2) #(space mismatch)
var.py
List1 = [(1,2), (3,4)]
test.robot(txt file)
*** Settings ***
Library BuiltIn
Library Collections
Variables var.py
Library String
*** Variables ***
#{appnd_li}
*** Test Cases ***
TEST
#constructing List2=["(1, 2)","(3, 4)"]
${List2}= Create List (1, 2) (3, 4)
# importing List1 from variable file
${len}= Get Length ${List1}
#initialize empty list
${li}= Create List #{appnd_li}
:FOR ${I} IN RANGE 0 ${len}
\ ${item}= Convert To String ${List1[${I}]}
\ Append To List ${li} ${item}
Lists Should Be Equal ${li} ${List2}
~
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
In my R code, I have the following content of x as a result of lda prediction output.
[1] lamb
Levels: lamb cow chicken
I would like to capture the word "lamb" in the first line and not the second line.
I had the following reg expression which did not work.
if (regmatches(x,regexec(".*?([a-z]+)",x))[[1]][2]=="lamb"){
cat("It is a lamb")
}
Instead, I also got the following error :-
Error in regexec(".*?([a-z]+)", x) : invalid 'text' argument
Anyone with help ?
Thanks in advance.
mf
Direct Answer:
It is a variable type error. See ?predict.lda to learn why: The return object of a predict() when used with an object of class lda is a list. You just want the first element of the list, which is a factor for an object of type integer. Factors in R store some characters for every element in their level component, which can be accessed by levels() (Read ?factor as well.). But what you want is to access the explicit value your factor shows, which can be acheived by as.character(). By the way: The second line does not get checked by the regex. It is just standard console output of a factor, see ?print.factor.
Here's an example, based on thepredict.lda() help page:
tr <- sample(1:50, 25)
train <- rbind(iris3[tr,,1], iris3[tr,,2], iris3[tr,,3])
test <- rbind(iris3[-tr,,1], iris3[-tr,,2], iris3[-tr,,3])
cl <- factor(c(rep("s",25), rep("c",25), rep("v",25)))
z <- lda(train, cl)
x_lda <- predict(z, test)
# x_lda is a list
typeof(x_lda)
# The first element of the list, called "class", is a factor of type integer.
typeof(x_lda$class)
# Now we create a character vector from the factor:
as.character(x_lda$class)
With an explicit character object, your code works for me:
x <- "lamb"
regmatches(x,regexec(".*?([a-z]+)",x))[[1]][2]=="lamb"
[1] TRUE
So you need to coerce your object to character, and then use it as the "text" argument for the regexec function.
Actual Answer:
There are better ways to do this.
You nest and chain a lot of functions in one line. This is barely readable and makes debugging hard.
If you know that the output will always consist of certain elements (especially, since you know the input of your lda prediction and therefore know the different factor levels beforehand), you can simply check them by == and maybe any() (continuing with the example from before):
levels(cl)
[1] "c" "s" "v"
any(as.character(x_lda$class)=="c")
[1] TRUE
See the help file for ?any, if you don't know what it does.
Finally, if you just want to print "It is a lamb" in the end, and your output will always just have one element, you can simply use paste():
paste("It is a", as.character(x))
[1] "It is a lamb"