PrimOps in GHCi - ghci

Is it possible to use PrimOps in GHCi? The following does not work:
$ ghci -XMagicHash
GHCi, version 8.10.1: https://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/stefan/.ghci
λ> let x = 42.0# :: Float#
<interactive>:1:18: error:
Not in scope: type constructor or class ‘Float#’
Perhaps you meant ‘Float’ (imported from Prelude)
Importing Prelude manually does not solve this error.
Update: After importing GHC.Exts the following error shows up:
$ ghci -XMagicHash
GHCi, version 8.10.1: https://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/stefan/.ghci
λ> import GHC.Exts
λ> let x = 42.0# :: Float#
<interactive>:1:1: error:
GHCi can't bind a variable of unlifted type: x :: Float#

The MagicHash extension just makes it legal to use # in names. If you want to specify types like Float#, you still need to import them. Do import GHC.Exts and try again.
Also, you can't bind them with let. You need to immediately use them and rewrap them.

Related

How to differentiate between a script and normal class files in Scala?

In the book, Programming in Scala 5th Edition, the author says the following for two classes:
Neither ChecksumAccumulator.scala nor Summer.scala are scripts, because they end in a definition. A script, by contrast, must end in a result expression.
The ChecksumAccumulator.scala is as follows:
import scala.collection.mutable
class CheckSumAccumulator:
private var sum = 0
def add(b: Byte): Unit = sum += b
def checksum(): Int = ~(sum & 0XFF) + 1
object CheckSumAccumulator:
private val cache = mutable.Map.empty[String, Int]
def calculate(s: String): Int =
if cache.contains(s) then
cache(s)
else
val acc = new CheckSumAccumulator
for c<-s do
acc.add((c >> 8).toByte)
acc.add(c.toByte)
val cs = acc.checksum()
cache += (s -> cs)
cs
whereas the Summer.scala is as follows:
import CheckSumAccumulator.calculate
object Summer:
def main(args: Array[String]): Unit =
for arg <- args do
println(arg + ": " + calculate(arg))
But when I run the Summer.scala file, I get a different error than what mentioned by the author:
➜ learning-scala git:(main) ./scala3-3.0.0-RC3/bin/scala Summer.scala
-- [E006] Not Found Error: /Users/avirals/dev/learning-scala/Summer.scala:1:7 --
1 |import CheckSumAccumulator.calculate
| ^^^^^^^^^^^^^^^^^^^
| Not found: CheckSumAccumulator
longer explanation available when compiling with `-explain`
1 error found
Error: Errors encountered during compilation
➜ learning-scala git:(main)
The author mentioned that the error would be around not having a result expression.
I also tried to compile CheckSumAccumulator only and then run Summer.scala as a script without compiling it:
➜ learning-scala git:(main) ./scala3-3.0.0-RC3/bin/scalac CheckSumAccumulator.scala
➜ learning-scala git:(main) ✗ ./scala3-3.0.0-RC3/bin/scala Summer.scala
<No output, given no input>
➜ learning-scala git:(main) ✗ ./scala3-3.0.0-RC3/bin/scala Summer.scala Summer of love
Summer: -121
of: -213
love: -182
It works.
Obviously, when I compile both, and then run Summer.scala, it works as expected. However, the differentiation of Summer.scala as a script vs normal file is unclear to me.
Let's start top-down...
The most regular way to compile Scala is to use a build tool like SBT/Maven/Mill/Gradle/etc. This build tool will help with a few things: downloading dependencies/libraries, downloading Scala compiler (optional), setting up CLASS_PATH and most importantly running scalac compiler and passing all flags to it. Additionally it can package compiled class files into JARs and other formats and do much more. Most relevant part is CP and compilation flags.
If you strip off the build tool you can compile your project by manually invoking scalac with all required arguments and making sure your working directory matches package structure, i.e. you are in the right directory. This can be tedious because you need to download all libraries manually and make sure they are on the class path.
So far build tool and manual compiler invocation are very similar to what you can also do in Java.
If you want to have an ah-hoc way of running some Scala code there are 2 options. scala let's you run scripts or REPL by simply compiling your uncompiled code before it executes it.
However, there are some caveats. Essentially REPL and shell scripts are the same - Scala wraps your code in some anonymous object and then runs it. This way you can write any expression without having to follow convention of using main function or App trait (which provides main). It will compile the script you are trying to run but will have no idea about imported classes. You can either compile them beforehand or make a large script that contains all code. Of course if it starts getting too large it's time to make a proper project.
So in a sense there is no such thing as script vs normal file because they both contain Scala code. The file you are running with scala is a script if it's an uncompiled code XXX.scala and "normal" compiled class XXX.class otherwise. If you ignore object wrapping I've mentioned above the rest is the same just different steps to compile and run them.
Here is the traditional 2.xxx scala runner code snippet with all possible options:
def runTarget(): Option[Throwable] = howToRun match {
case AsObject =>
ObjectRunner.runAndCatch(settings.classpathURLs, thingToRun, command.arguments)
case AsScript if isE =>
ScriptRunner(settings).runScriptText(combinedCode, thingToRun +: command.arguments)
case AsScript =>
ScriptRunner(settings).runScript(thingToRun, command.arguments)
case AsJar =>
JarRunner.runJar(settings, thingToRun, command.arguments)
case Error =>
None
case _ =>
// We start the repl when no arguments are given.
if (settings.Wconf.isDefault && settings.lint.isDefault) {
// If user is agnostic about -Wconf and -Xlint, enable -deprecation and -feature
settings.deprecation.value = true
settings.feature.value = true
}
val config = ShellConfig(settings)
new ILoop(config).run(settings)
None
}
This is what's getting invoked when you run scala.
In Dotty/Scala3 the idea is similar but split into multiple classes and classpath logic might be different: REPL, Script runner. Script runner invokes repl.

Use a variable in a shell command in a Scala program (not REPL)

Inside a program - not the REPL - is it possible to introduce a string variable to represent the shell command to be executed ?
import sys.process._
val npath = opath.substring(0,opath.lastIndexOf("/"))
s"rm -rf $npath/*" !
s"mv $tmpName/* $npath/" !
The compiler says:
:103: error: type mismatch;
found : String
required: scala.sys.process.ProcessLogger
s"mv $tmpName/* $npath/" !
^
Note that in the REPL this can be fixed by using
:power
But .. we're not in the REPL here.
I found a useful workaround that mostly preserves the intended structure:
Use the
Seq[String].!
syntax. But by using spaces as a delimiter we can still write it out in a kind of wysiwig way
import sys.process._
val npath = opath.substring(0,opath.lastIndexOf("/"))
s"rm -rf $npath/*".split(" ").toSeq.!
s"mv $tmpName/* $npath/".split(" ").toSeq.!
The limitation here is that embedded spaces in the command would not work - they would require an explicit Seq of each portion of the command.
Here is a bit nicer if there were a set of commands to run:
Seq(s"rm -rf $npath/*",s"mv $tmpName/* $npath/").foreach{ cmd=>
println(cmd)
cmd.split(" ").toSeq.!
}

Scala: Import scala.io.StdIn.readLIne -- error importing

I am getting an error if I import readline, as follows:
import scala.io.StdIn.{readline, readInt} =>
error: value readline is not a member of object scala.io.StdIn
import scala.io.StdIn.{readline, readInt}
Scala code runner version 2.12.1
If I don't import this, I get a deprecated message:
warning: there was one deprecation warning (since 2.11.0); re-run with -deprecation for details
one warning found
I get no errors if I use the fill path to the function:
var x = scala.io.StdIn.readLine.toInt
Let me know if you can help me resolve the import. Thanks.
A very tiny overlook:
import scala.io.StdIn.{readLine, readInt}
readLine has an upper case L

Macros in the Cider repl (e.g. ->)

why is the use of the threading macro ->> producing an error in the cider-repl:
(-> "x..")
// Unable to resolve symbol: -> in this context
this happens when you create a new namespace in the repl and have not yet defined anything in it. so the aliases for the clojure.core functions have not yet been established:
start by creating a new blank namespace:
user> (in-ns 'i-dont-exist-yet)
#namespace[i-dont-exist-yet]
Then try to use the threading macro (or anything from clojure.core):
i-dont-exist-yet> (-> 1)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: -> in this context, compiling:(*cider-repl api*:47:18)
which fails to lookup the symbol -> in the current namespace, though it works if you tell it which namespace to use explicitly:
i-dont-exist-yet> (clojure.core/-> 1)
1
There is a convenience function in clojure.core that will add all the expected refers for your new namespce. You won't need to do this when you create your namespace from a file with the ns macro at the top because ns does this for you (amongst other useful things):
i-dont-exist-yet> (clojure.core/refer-clojure)
nil
i-dont-exist-yet> (-> 1)
1

Compiling Multiple Files with modules

I am programming in Fortran 90 using GFortran and I'm having troubles with Modules. When I compile the code below, I get the following error:
Derivatives.f90:7.16:
Included at C:\Users\dchalhub\Dropbox\Doutorado\#Tese\New folder\main.f90:1:
Use Mesh
1
Fatal Error: Can't open module file 'mesh.mod' for reading at (1): No such file or directory
gfortran.exe: Internal error: Aborted (program f951)
Please submit a full bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.
So, the 'mesh.mod' file is not created.
But when I remove the first two lines: 'include 'Derivatives.f90'' and 'include 'Poisson.f90'' the module is created without any problems.
After the mod file is created, I put back the first two lines, compile the code again and it works perfectly.
include 'Derivatives.f90'
include 'Poisson.f90'
!**************************************************************
MODULE MESH
IMPLICIT NONE
INTEGER :: IMAX,JMAX,NMAX
REAL(8), ALLOCATABLE :: XD(:),YD(:),FX(:,:),FY(:,:)
REAL(8) :: PI,E,DX,DY,H,L,RHO,MU
PARAMETER (PI = ACOS(-1.D0))
PARAMETER (E = 2.71828182845904523536028747135266249775724709369995)
END MODULE MESH
!**************************************************************
!**************************************************************
!*********** Lid-driven Cavity Program*************************
!**************************************************************
program Cavity
Use Mesh
implicit none
End program Cavity
I don't know why but there is something wrong with compiling multiple files with modules.
Does any one know what should I do to make it work properly?