I didn't touch Prolog since high-school, and even though I've tried to find the info, it didn't help. Below is the example that has to illustrate my problem:
%% everybody():- [dana, cody, bess, abby].
%% Everybody = [dana, cody, bess, abby].
likes(dana, cody).
hates(bess, dana).
hates(cody, abby).
hates(X, Y):- \+ likes(X, Y).
likes_somebody(_, []):- fail.
likes_somebody(X, [girl | others]):-
likes(X, girl) ; likes_somebody(X, others).
likes_everybody(_, []):- true.
likes_everybody(X, [girl | others]):-
likes(X, girl) , likes_everybody(X, others).
maplist(likes_somebody, [dana, cody, bess, abby], [dana, cody, bess, abby]).
How do I declare everybody to just be the list of girls? The commented lines are those which I've tried, but I've got bizarre error messages back.
This is the tutorial I followed more or less so far. I'm using GProlog, if it makes any difference. Sorry for such a basic question. GProlog's manual doesn't deal with language syntax, but I've certainly looked there. As an aside, I would be grateful for information on where to look for language documentation (as opposed to implementation documentation).
Every variable in Prolog must begin with an uppercase letter. So for starters, you want Everybody, not everybody.
Second problem, variables in Prolog are not assignables. So probably what you want to do is make a fact and use that instead:
everybody([dana, cody, bess, abby]).
Your bottom line of code is actually a fact definition and will attempt to overwrite maplist/3. What you probably want to do is put everything above that line into a file (say, called likes.pl) and then consult it ([likes].). Then you can run a query like this:
?- everybody(Everybody), maplist(likes_somebody, Everybody, Everybody).
This won't work, because likes_somebody/2 processes a list in the second argument. The predicate you have for likes_somebody/2 could be written:
likes_somebody(_, []).
but still won't mean much. It simply unifies anything with the empty list:
?- likes_somebody(chicken_tacos, []).
true.
You really need a predicate to tell you if someone is a girl, like this:
girl(dana).
girl(cody).
girl(bess).
girl(abby).
Then you could do what I think you're trying to do, which is something closer to this:
likes_somebody(X) :- girl(X).
Then the maplist construction would work like this:
everybody(Everybody), maplist(likes_somebody, Everybody).
Which would simply return true. You could simplify and eliminate everybody/1 by instead using findall(Girl, girl(X), Everybody) but it's getting weird.
You're trying to do list processing with likes_everybody/2, but it's broken because girl is literally girl, not a variable, and others is literally others, not a list of some kind that could be the tail of another list.
I think you still have some old ideas you need to cleanse. Read some more, write some more, and your code will start to make a lot more sense.
Related
to is an infix function within the standard library. It can be used to create Pairs concisely:
0 to "hero"
in comparison with:
Pair(0, "hero")
Typically, it is used to initialize Maps concisely:
mapOf(0 to "hero", 1 to "one", 2 to "two")
However, there are other situations in which one needs to create a Pair. For instance:
"to be or not" to "be"
(0..10).map { it to it * it }
Is it acceptable, stylistically, to (ab)use to in this manner?
Just because some language features are provided does not mean they are better over certain things. A Pair can be used instead of to and vice versa. What becomes a real issue is that, does your code still remain simple, would it require some reader to read the previous story to understand the current one? In your last map example, it does not give a hint of what it's doing. Imagine someone reading { it to it * it}, they would be most likely confused. I would say this is an abuse.
to infix offer a nice syntactical sugar, IMHO it should be used in conjunction with a nicely named variable that tells the reader what this something to something is. For example:
val heroPair = Ironman to Spiderman //including a 'pair' in the variable name tells the story what 'to' is doing.
Or you could use scoping functions
(Ironman to Spiderman).let { heroPair -> }
I don't think there's an authoritative answer to this. The only examples in the Kotlin docs are for creating simple constant maps with mapOf(), but there's no hint that to shouldn't be used elsewhere.
So it'll come down to a matter of personal taste…
For me, I'd be happy to use it anywhere it represents a mapping of some kind, so in a map{…} expression would seem clear to me, just as much as in a mapOf(…) list. Though (as mentioned elsewhere) it's not often used in complex expressions, so I might use parentheses to keep the precedence clear, and/or simplify the expression so they're not needed.
Where it doesn't indicate a mapping, I'd be much more hesitant to use it. For example, if you have a method that returns two values, it'd probably be clearer to use an explicit Pair. (Though in that case, it'd be clearer still to define a simple data class for the return value.)
You asked for personal perspective so here is mine.
I found this syntax is a huge win for simple code, especial in reading code. Reading code with parenthesis, a lot of them, caused mental stress, imagine you have to review/read thousand lines of code a day ;(
I am using a MixHash to combine two Hashes with the Bag add (+) operator. This seems to work - but ... I am a bit surprised that the result of the union needs to be re-coerced back to a MixHash.
My guess is that the Bag add (+) infix operator coerces everything to a Bag first and returns the result as a Bag. This may be risky for me as some of my weights are negative (thus the Mix in the first place). Will this properly add negative weights?
Alternatively, is there a Mix add (+) operator?
my MixHash $dim-mix;
for ... {
my $add-mix = $!dims.MixHash;
$dim-mix = $dim-mix ?? ( $dim-mix (+) $add-mix ).MixHash !! $add-mix;
}
dd $dim-mix;
Now I look at this paraphrased code, perhaps there is some formulation of ternary ?? !! that can avoid spelling out $dim-mix in the test since already on the left?
Many thanks for any advice!
my $add-mix = (foo => 0.22, bar => -0.1).Mix;
my $dim-mix;
for ^5 {
$dim-mix (+)= $add-mix;
}
dd $dim-mix; # Mix $dim-mix = ("foo"=>1.1,"bar"=>-0.5).Mix
Obviously I've not used a MixHash, but you can sort that out if you need to after the loop.
(And of course you might be thinking "but isn't a Mix immutable?" It is -- but you have to distinguish variables and values. $dim-mix is a variable, a Scalar variable. Even if you type it -- my Mix $dim-mix; it's still a Scalar variable holding a Mix value. You can always assign to a Scalar.)
I'm starting to get a routine for questions like this where I don't know what's going on but I think I ought to be able to figure it out. Here was my process:
I got your code to run to see what it did. I tried to simplify the ternary. Hmm.
I turned to the doc. There was the doc page for (+). That called it "Baggy addition". That was worrisome given that a Bag only holds (positive) integers.
I turned to the source. I fired off a search of the rakudo sources for "Baggy addition". One result. I focused on the multi with (Mixy:D $a, QuantHash:D $b) signature. This showed me that the result should stay Mixy, i.e. the doc's implication it would or could go Baggy is a red herring.
I returned to the code and started wondering what I could do. When I initially tried to use (+)= to simplify the main assignment the compiler complained expected MixHash but got Mix. I tried a half dozen things that didn't work then just changed the MixHash constraint on $dim-mix to Mixy and it worked.
Then I thought through what was going on and realized that almost all the types were getting in the way of P6 just doing the right thing.
You can add some types back in if you really need them.
(But do you really need them? When types are absolutely necessary they're great. Otherwise, imo, think twice, and then twice again, before introducing them. They can easily make code harder to read, reason about, compose, and slower.)
(Of course there are occasions on which they're not strictly necessary but do really help overall. Imo, as with all things, keep it simple at first and only complexify if you see clear benefits for a particular line of code.)
Okay, what I really wanted to do is, I have an Array and I want to choose a random element from it. The obvious thing to do is get an integer from a random number generator between 0 and the length minus 1, which I have working already, and then applying Array.get, but that returns a Maybe a. (It appears there's also a package function that does the same thing.) Coming from Haskell, I get the type significance that it's protecting me from the case where my index was out of range, but I have control over the index and don't expect that to happen, so I'd just like to assume I got a Just something and somewhat forcibly convert to a. In Haskell this would be fromJust or, if I was feeling verbose, fromMaybe (error "some message"). How should I do this in Elm?
I found a discussion on the mailing list that seems to be discussing this, but it's been a while and I don't see the function I want in the standard library where the discussion suggests it would be.
Here are some pretty unsatisfying potential solutions I found so far:
Just use withDefault. I do have a default value of a available, but I don't like this as it gives the completely wrong meaning to my code and will probably make debugging harder down the road.
Do some fiddling with ports to interface with Javascript and get an exception thrown there if it's Nothing. I haven't carefully investigated how this works yet, but apparently it's possible. But this just seems to mix up too many dependencies for what would otherwise be simple pure Elm.
(answering my own question)
I found two more-satisfying solutions:
Roll my own partially defined function, which was referenced elsewhere in the linked discussion. But the code kind of feels incomplete this way (I'd hope the compiler would warn me about incomplete pattern matches some day) and the error message is still unclear.
Pattern-match and use Debug.crash if it's a Nothing. This appears similar to Haskell's error and is the solution I'm leaning towards right now.
import Debug
fromJust : Maybe a -> a
fromJust x = case x of
Just y -> y
Nothing -> Debug.crash "error: fromJust Nothing"
(Still, the module name and description also make me hesitate because it doesn't seem like the "right" method intended for my purposes; I want to indicate true programmer error instead of mere debugging.)
Solution
The existence or use of a fromJust or equivalent function is actually code smell and tells you that the API has not been designed correctly. The problem is that you're attempting to make a decision on what to do before you have the information to do it. You can think of this in two cases:
If you know what you're supposed to do with Nothing, then the solution is simple: use withDefault. This will become obvious when you're looking at the right point in your code.
If you don't know what you're supposed to do in the case where you have Nothing, but you still want to make a change, then you need a different way of doing so. Instead of pulling the value out of the Maybe use Maybe.map to change the value while keeping the Maybe. As an example, let's say you're doing the following:
foo : Maybe Int -> Int
foo maybeVal =
let
innerVal = fromJust maybeVal
in
innerVal + 2
Instead, you'll want this:
foo : Maybe Int -> Maybe Int
foo maybeVal =
Maybe.map (\innerVal -> innerVal + 2) maybeVal
Notice that the change you wanted is still done in this case, you've simply not handled the case where you have a Nothing. You can now pass this value up and down the call chain until you've hit a place where it's natural to use withDefault to get rid of the Maybe.
What's happened is that we've separated the concerns of "How do I change this value" and "What do I do when it doesn't exist?". We deal with the former using Maybe.map and the latter with Maybe.withDefault.
Caveat
There are a small number of cases where you simply know that you have a Just value and need to eliminate it using fromJust as you described, but those cases should be few and far between. There's quite a few that actually have a simpler alternative.
Example: Attempting to filter a list and get the value out.
Let's say you have a list of Maybes that you want the values of. A common strategy might be:
foo : List (Maybe a) -> List a
foo hasAnything =
let
onlyHasJustValues = List.filter Maybe.isJust hasAnything
onlyHasRealValues = List.map fromJust onlyHasJustValues
in
onlyHasRealValues
Turns out that even in this case, there are clean ways to avoid fromJust. Most languages with a collection that has a map and a filter have a method to filter using a Maybe built in. Haskell has Maybe.mapMaybe, Scala has flatMap, and Elm has List.filterMap. This transforms your code into:
foo : List (Maybe a) -> List a
foo hasAnything =
let
onlyHasRealValues = List.filterMap (\x -> x) hasAnything
in
onlyHasRealValues
I have got a term from which I want to get set of variables name.
Eg. input: my_m(aa,b,B,C,max(D,C),D)
output: [B,C,D] (no need to be ordered as order of appearance in input)
(That would call like set_variable_name(Input,Output).)
I can simply get [B,C,D,C,D] from the input, but don't know how to implement set (only one appearance in output). I've tried something like storing in rbtrees but that failed, because of
only_one([],T,T) :- !.
only_one([X|XS],B,C) :- rb_in(X,X,B), !, only_one(XS,B,C).
only_one([X|XS],B,C) :- rb_insert(B,X,X,U), only_one(XS,U,C).
it returns tree with only one node and unification like B=C, C=D.... I think I get it why - because of unification of X while questioning rb_in(..).
So, how to store only once that name of variable? Or is that fundamentally wrong idea because we are using logic programming? If you want to know why I need this, it's because we are asked to implement A* algorithm in Prolog and this is one part of making search space.
You can use sort/2, which also removes duplicates.
In this question, a user commented to never use the With block in VB. Why?
"Never" is a strong word.
I think it fine as long as you don't abuse it (like nesting)
IMHO - this is better:
With MyCommand.Parameters
.Count = 1
.Item(0).ParameterName = "#baz"
.Item(0).Value = fuz
End With
Than:
MyCommand.Parameters.Count = 1
MyCommand.Parameters.Item(0).ParameterName = "#baz"
MyCommand.Parameters.Item(0).Value = fuz
There is nothing wrong about the With keyword. It's true that it may reduce readibility when nested but the solution is simply don't use nested With.
There may be namespace problems in Delphi, which doesn't enforce a leading dot but that issue simply doesn't exist in VB.NET so the people that are posting rants about Delphi are losing their time in this question.
I think the real reason many people don't like the With keyword is that is not included in C* languages and many programmers automatically think that every feature not included in his/her favourite language is bad.
It's just not helpful compared to other options.
If you really miss it you can create a one or two character alias for your object instead. The alias only takes one line to setup, rather than two for the With block (With + End With lines).
The alias also gives you a quick mouse-over reference for the type of the variable. It provides a hook for the IDE to help you jump back to the top of the block if you want (though if the block is that large you have other problems). It can be passed as an argument to functions. And you can use it to reference an index property.
So we have an alternative that gives more function with less code.
Also see this question:
Why is the with() construct not included in C#, when it is really cool in VB.NET?
The with keyword is only sideswiped in a passing reference here in an hilarious article by the wonderful Verity Stob, but it's worth it for the vitriol: See the paragraph that starts
While we are on identifier confusion. The with keyword...
Worth reading the entire article!
The With keyword also provides another benefit - the object(s) in the With statement only need to be "qualified" once, which can improve performance. Check out the information on MSDN here:
http://msdn.microsoft.com/en-us/library/wc500chb(VS.80).aspx
So by all means, use it.