I have a question concerning the order of operations in Solidity. In the docs it says that the logical NOT operation takes precedence over the logical AND operation. The thing is, when I have an if statement like that if(false && !function()) I thought the function is called first because of the order of operations, but in reality the short-circuiting of the && operator is done first. So my question is: Why?
It's because the two operators || and && apply the common short-circuiting rules, as described in Solidity document:
The operators || and && apply the common short-circuiting rules. This means that in the expression f(x) || g(y), if f(x) evaluates to true, g(y) will not be evaluated even if it may have side-effects.
Because of the common short-circuiting rules, the behavior described here is exactly the same as many other languages, e.g Java or Scala. Here is a Scala REPL demonstration:
scala> def foo(x: Int): Boolean = { if (x >= 0) true else ??? }
foo: (x: Int)Boolean
scala> foo(10)
res0: Boolean = true
scala> foo(-10)
scala.NotImplementedError: an implementation is missing
at scala.Predef$.$qmark$qmark$qmark(Predef.scala:230)
at .foo(<console>:11)
... 32 elided
scala> if (false && !foo(-10)) "boo" else "bar"
res2: String = bar
Related
I am generating input to be compiled by Chisel. Doing it the easy way might result in suboptimal boolean expressions. For example, I tend to generate chains of nested Mux()-es, like this:
x :=
Mux(!a && !b && !c && d, 13,
Mux(!a && !b && c, 3,
Mux(!a && !b, 2,
Mux(!a && b, temp1,
Mux(a && e, 11,
Mux(a, 0,
-1))))))
As you can see,
some of the boolean expressions are repeated, such as "!a", so likely some optimization could be done to express the same function using fewer evaluations, such as common sub-expression elimination,
tests are repeated, again, such as "!a", so likely some optimization could be done to factor that out and test it once instead, and
similar to point 2 above, the expression is very deep, so likely some optimization could be done to make it more like a tree and less like a linear sequence of Mux-es.
One thing I do not do is have complex predicate expressions: every predicate is just a conjunction of terms and each term is just a var or its negation.
I could try to implement these kind of transforms in my code generator, but in doing so I would end up writing my own optimizing compiler for boolean expressions. Instead can I just generate the above and rely on the Chisel/FIRRTL toolchain to optimize boolean expressions of this level of complexity? Such expressions are likely to be about the size of the one above or up to maybe twice its size.
The FIRRTL compiler does support Common Subexpression Elimination (CSE), but not Global Value Numbering (GVN). In effect, you can expect that most common subexpressions will be combined as you'd expect in emitted Verilog.
The FIRRTL compiler does not do mux tree optimization. The synthesis tool should be able to optimized whatever it's given, but it's sadly not always the case. Therefore, Chisel and the FIRRTL compiler choose to not do mux tree optimization to preserve the intent of the user. Commonly, the user is writing some specific Chisel intended to be optimized in a certain way by the synthesis tool. If the FIRRTL compiler reorders the mux tree and produces a quality of result (QOR) regression, that's really bad. Consider this comment for more context.
That said, if a user really wants to apply some mux reordering at the FIRRTL-level, they can write a custom FIRRTL optimization transform (that may be scoped to only the module/region they want to optimize). This could be a good optional feature of the FIRRTL compiler. This is also an option available if you're generating Chisel---it may be simpler to write an optimization over FIRRTL IR instead of in the Chisel generation library.
Now, how does this interact with the original example? Start with a slightly simplified version:
import chisel3._
import chisel3.internal.sourceinfo.UnlocatableSourceInfo
class Foo extends RawModule {
private implicit val noInfo = UnlocatableSourceInfo
val a = IO(Input(Bool()))
val b = IO(Input(Bool()))
val c = IO(Input(Bool()))
val d = IO(Input(Bool()))
val e = IO(Input(Bool()))
val x = IO(Output(UInt()))
x := Mux(!a && !b && !c && d, 1.U,
Mux(!a && !b && c, 2.U,
Mux(!a && !b, 3.U,
Mux(!a && b, 4.U,
Mux(a && e, 5.U,
Mux(a, 6.U, 0.U))))))
}
When compiled with Chisel 3.3.2 and FIRRTL 1.3.2, the following Verilog is the result:
module Foo(
input a,
input b,
input c,
input d,
input e,
output [2:0] x
);
wire _T = ~a;
wire _T_1 = ~b;
wire _T_2 = _T & _T_1;
wire _T_3 = ~c;
wire _T_4 = _T_2 & _T_3;
wire _T_5 = _T_4 & d;
wire _T_9 = _T_2 & c;
wire _T_14 = _T & b;
wire _T_15 = a & e;
wire [2:0] _T_16 = a ? 3'h6 : 3'h0;
wire [2:0] _T_17 = _T_15 ? 3'h5 : _T_16;
wire [2:0] _T_18 = _T_14 ? 3'h4 : _T_17;
wire [2:0] _T_19 = _T_2 ? 3'h3 : _T_18;
wire [2:0] _T_20 = _T_9 ? 3'h2 : _T_19;
assign x = _T_5 ? 3'h1 : _T_20;
endmodule
Observations:
CSE is doing it's job, e.g., ~a & ~b is put in _T_2 and reused.
The mux tree structure is unmodified.
Chisel does have a reduceTree method defined for Vec which can be used to produce balanced mux trees. Also, the chain of muxes in the original example can be perhaps more scalably described with util.MuxCase (without affecting the resulting mux tree):
x := MuxCase(
default = 0.U,
mapping = Seq(
(!a && !b && !c && d) -> 1.U,
(!a && !b && c) -> 2.U,
(!a && !b) -> 3.U,
(!a && b) -> 4.U,
(a && e) -> 5.U,
(a) -> 6.U)
)
Say I have a List that looks like this:
let identifiers = ["ABC123", "DEF456", "GHI789"]
I want to know the index if the element "DEF456". What's the recommended way to accomplish this?
In daml 1.2 you can use the elemIndex : Eq a => a -> [a] -> Optional Int function in the DA.List standard library module like so:
daml 1.2 module MyModule where
import DA.List
indexOfElement = scenario do
let identifiers = ["ABC123", "DEF456", "GHI789"]
index : Optional Int = elemIndex "DEF456" identifiers
assert $ index == Some 1
return index
The findIndex function in the Base.List module in the standard library, does what you want.
daml 1.0 module FindIndex where
import Base.List
import Base.Maybe
test foo : Scenario {} = scenario
let
identifiers = ["ABC123", "DEF456", "GHI789"]
index: Maybe Integer = findIndex ((==) "DEF456") identifiers
assert $ index == Just 1
Under the hood most list manipulation in DAML, including findIndex is implemented using foldr and foldl.
-- Returns the index of the first element in the list satisfying the predicate, or M.Nothing if there is no such element.
def findIndex (f: a -> Bool) (xs: List a) : Maybe Integer =
headMay (findIndices f xs)
-- Returns the indices of all elements satisfying the predicate, in ascending order.
def findIndices (f: a -> Bool) (xs: List a) =
let work acc x =
let i = fst acc
let is = snd acc
tuple (i + 1) (if f x then cons i is else is)
reverse (snd (foldl work (tuple 0 nil) xs))
I want to make a function in standard ml that checks if a tree is complete or not, the function somehow works, but its giving me the wrong type and a warning of non-exhaustive cases
The tree code:
datatype 'data tree =
EMPTY
| NODE of 'data tree * 'data * 'data tree;
fun isComplete EMPTY = true
| isComplete (NODE(x, y, z)) = if (x = EMPTY andalso z <> EMPTY) orelse (x <> EMPTY andalso z = EMPTY) then false else true;
Now the above function's type is: ''a tree -> bool but the required type is 'a tree -> bool
The warning I'm having is:
stdIn:169.8 Warning: calling polyEqual
stdIn:169.26 Warning: calling polyEqual
stdIn:169.45-169.47 Warning: calling polyEqual
stdIn:169.64-169.66 Warning: calling polyEqual
stdIn:124.1-169.94 Warning: match nonexhaustive
NODE (x,y,z) => ...
What is the problem I'm having?
EDIT:
Thanks to Michael, I fixed the code and now it works:
- fun isComplete EMPTY = true
| isComplete (NODE(EMPTY, _, EMPTY)) = true
| isComplete (NODE(NODE(x, y, z), _, NODE(a, b, c))) = true
| isComplete (EMPTY, _, NODE(x, y, z)) = false
| isComplete (NODE(x, y, z), _, EMPTY) = false;
The ''a tree -> bool type indicates that a is an equality type: it must be a type that supports testing with equals. Since you are using = and <> to test x and z, the tree data must support equality (even though you're not doing anything interesting with the values). This is the root of the polyEqual warning.
The nonexhaustive match warning is more puzzling. When I paste your datatype and function definitions into Moscow ML, I do not get a warning. I don't think I'd worry about it too much, as I'd expect fixing the type to also take care of the warning.
To get the desired type 'a tree -> bool, I'd suggest getting rid of the if in favor of pattern matching. E.g.:
fun isComplete EMPTY = true
| isComplete (NODE(EMPTY, _, EMPTY)) = true
| isComplete (NODE(EMPTY, _, NODE(x,y,z))) = false
| ... (* fill out the rest of the cases *)
I'll leave it to you to figure out the full set of cases, as this looks like homework.
Incidentally, I don't think your test for completeness is correct. Consider what happens when neither subtree is EMPTY: you call the tree complete without considering the contents. This doesn't have anything to do with the warnings you're seeing, though.
Concerning the polyEqual warning: in SML/NJ this warning is printed everytime you use this operator, but that doesn't mean your code is faulty. Here's a blog post about it, and in the comments someone explains why the warning is given: http://abstractfactory.blogspot.fr/2006/05/sml-hacking-tip-turn-off-polyequal.html
I'm an OCaml noob. I'm trying to figure out how to handle a comparison operator that's passed into a function.
My function just tries to pass in a comparison operator (=, <, >, etc.) and an int.
let myFunction comparison x =
if (x (comparison) 10) then
10
else
x;;
I was hoping that this code would evaluate to (if a "=" were passed in):
if (x = 10) then
10
else
x;;
However, this is not working. In particular, it thinks that x is a bool, as evidenced by this error message:
This expression has type 'a -> int -> bool
but an expression was expected of type int
How can I do what I'm trying to do?
On a side question, how could I have figured this out on my own so I don't have to rely on outside help from a forum? What good resources are available?
Comparison operators like < and = are secretly two-parameter (binary) functions. To pass them as a parameter, you use the (<) notation. To use that parameter inside your function, you just treat it as function name:
let myFunction comp x =
if comp x 10 then
10
else
x;;
printf "%d" (myFunction (<) 5);; (* prints 10 *)
OCaml allows you to treat infix operators as identifiers by enclosing them in parentheses. This works not only for existing operators but for new ones that you want to define. They can appear as function names or even as parameters. They have to consist of symbol characters, and are given the precedence associated with their first character. So if you really wanted to, you could use infix notation for the comparison parameter of myFunction:
Objective Caml version 3.12.0
# let myFunction (#) x =
x # 10;;
val myFunction : ('a -> int -> 'b) -> 'a -> 'b = <fun>
# myFunction (<) 5;;
- : bool = true
# myFunction (<) 11;;
- : bool = false
# myFunction (=) 10;;
- : bool = true
# myFunction (+) 14;;
- : int = 24
#
(It's not clear this makes myFunction any easier to read. I think definition of new infix operators should be done sparingly.)
To answer your side question, lots of OCaml resources are listed on this other StackOverflow page:
https://stackoverflow.com/questions/2073436/ocaml-resources
Several possibilities:
Use a new definition to redefine your comparison operator:
let myFunction comparison x =
let (#) x y = comparison x y in
if (x # 10) then
10
else
x;;
You could also pass the # directly without the extra definition.
As another solution you can use some helper functions to define what you need:
let (/*) x f = f x
let (*/) f x = f x
let myFunction comparison x =
if x /* comparison */ 10 then
10
else
x
Does Scala have an operator similar to Haskell's $?
-- | Application operator. This operator is redundant, since ordinary
-- application #(f x)# means the same as #(f '$' x)#. However, '$' has
-- low, right-associative binding precedence, so it sometimes allows
-- parentheses to be omitted; for example:
--
-- > f $ g $ h x = f (g (h x))
--
-- It is also useful in higher-order situations, such as #'map' ('$' 0) xs#,
-- or #'Data.List.zipWith' ('$') fs xs#.
{-# INLINE ($) #-}
($) :: (a -> b) -> a -> b
f $ x = f x
Yes, it's written "apply"
fn apply arg
There's no standard punctuation operator for this, but it would be easy enough to add one via library pimping.
class RichFunction[-A,+B](fn: Function1[A, B]){ def $(a:A):B = fn(a)}
implicit def function2RichFunction[-A,+B](t: Function1[A, B]) = new RichFunction[A, B](t)
In general, while Scala code is much denser than Java, it's not quite as dense as Haskell. Thus, there's less payoff to creating operators like '$' and '.'