当前位置:  开发笔记 > 编程语言 > 正文

是否有适合编写脚本的快速启动Haskell解释器?

如何解决《是否有适合编写脚本的快速启动Haskell解释器?》经验,为你挑选了3个好方法。

有没有人知道一个快速启动的Haskell解释器适合用于编写shell脚本?使用Hugs运行'hello world'在我的旧笔记本电脑上运行了400ms,在我当前的Thinkpad X300上运行了300ms.这对于瞬时响应来说太慢了.与GHCi的时代相似.

功能语言不一定要慢:Objective Caml和Moscow ML在1ms或更短的时间内运行hello world.

澄清:我是GHC的重度用户,我知道如何使用GHCi.我知道所有关于编译以使事情变得快速的事情.解析成本应该完全无关:如果ML和OCaml的启动速度比GHCi快300倍,那么还有改进的余地.

我在寻找

脚本的便利性:一个源文件,没有二进制代码,相同的代码在所有平台上运行

性能可与其他解释器相媲美,包括快速启动和执行简单程序等

module Main where
main = print 33

不是在寻找更严肃程序的编译性能.重点是看看Haskell是否对脚本有用.



1> srparish..:

为什么不创建一个脚本前端来编译脚本(如果它以前没有,或者编译后的版本已经过时).

这是基本的想法,这个代码可以进行很多改进 - 搜索路径而不是假设所有内容都在同一个目录中,更好地处理其他文件扩展名等.另外,我在haskell编码时非常环保(ghc-compiled-script. HS):

import Control.Monad
import System
import System.Directory
import System.IO
import System.Posix.Files
import System.Posix.Process
import System.Process

getMTime f = getFileStatus f >>= return . modificationTime

main = do
  scr : args <- getArgs
  let cscr = takeWhile (/= '.') scr

  scrExists <- doesFileExist scr
  cscrExists <- doesFileExist cscr
  compile <- if scrExists && cscrExists
               then do
                 scrMTime <- getMTime scr
                 cscrMTime <- getMTime cscr
                 return $ cscrMTime <= scrMTime
               else
                   return True

  when compile $ do
         r <- system $ "ghc --make " ++ scr
         case r of
           ExitFailure i -> do
                   hPutStrLn stderr $
                            "'ghc --make " ++ scr ++ "' failed: " ++ show i
                   exitFailure
           ExitSuccess -> return ()

  executeFile cscr False args Nothing

现在我们可以创建这样的脚本(hs-echo.hs):

#! ghc-compiled-script

import Data.List
import System
import System.Environment

main = do
  args <- getArgs
  putStrLn $ foldl (++) "" $ intersperse " " args

现在运行它:

$ time hs-echo.hs "Hello, world\!"     
[1 of 1] Compiling Main             ( hs-echo.hs, hs-echo.o )
Linking hs-echo ...
Hello, world!
hs-echo.hs "Hello, world!"  0.83s user 0.21s system 97% cpu 1.062 total

$ time hs-echo.hs "Hello, world, again\!"
Hello, world, again!
hs-echo.hs "Hello, world, again!"  0.01s user 0.00s system 60% cpu 0.022 total



2> ephemient..:

使用ghc -e几乎等同于调用ghci.我相信GHC会runhaskell在运行之前将代码编译为临时可执行文件,而不是将其解释为ghc -e/ ghci,但我不是100%肯定的.

$ time echo 'Hello, world!'
Hello, world!

real    0m0.021s
user    0m0.000s
sys     0m0.000s
$ time ghc -e 'putStrLn "Hello, world!"'
Hello, world!

real    0m0.401s
user    0m0.031s
sys     0m0.015s
$ echo 'main = putStrLn "Hello, world!"' > hw.hs
$ time runhaskell hw.hs
Hello, world!

real    0m0.335s
user    0m0.015s
sys     0m0.015s
$ time ghc --make hw
[1 of 1] Compiling Main             ( hw.hs, hw.o )
Linking hw ...

real    0m0.855s
user    0m0.015s
sys     0m0.015s
$ time ./hw
Hello, world!

real    0m0.037s
user    0m0.015s
sys     0m0.000s

在运行它们之前简单地编译所有"脚本"有多难?

编辑

啊,为多种架构提供二进制文件确实很痛苦.我之前走过这条路,这并不是很有趣......

遗憾的是,我认为不可能更好地使任何Haskell编译器的启动开销.语言的声明性意味着有必要首先阅读整个程序,甚至在尝试进行类型检查之前,从不执行任何操作,然后您要么承担严格性分析或不必要的懒惰和thunking的成本.

流行的"脚本"语言(shell,Perl,Python等)和基于ML的语言只需要一次通过......好吧,ML需要静态类型检查传递,Perl有这种有趣的5遍方案(带有其中两个反向运行); 无论哪种方式,程序化意味着编译器/解释器更容易将程序的各个部分组合在一起.

简而言之,我认为不可能比这更好.我还没有测试看看Hugs或GHCi是否有更快的启动,但任何差异仍然远离非Haskell语言.


我使用三种不同的计算平台:x86,amd64和sparc.编译所有三个代码的不便很重要.我在Lua和`ksh`中写了很多*脚本,我宁愿使用Haskell.但是,如果我必须编译所有内容.

3> 小智..:

如果您真的关心速度,那么每次启动时重新解析代码都会受到阻碍.Haskell不需要从解释器运行,用GHC编译它就可以获得出色的性能.

推荐阅读
虎仔球妈_459
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有