尾递归是函数式语言中一个重要的性能优化策略,因为它允许递归调用消耗常量堆栈(而不是O(n)).
是否有任何问题根本无法以尾递归方式编写,或者总是可以将天真递归函数转换为尾递归函数?
如果是这样,有一天功能编译器和解释器可能足够智能以自动执行转换?
生成一个列表列表(或打印,我不介意)一个大小为N 的Pascal三角形,代码可能最少!
这是我的尝试(使用技巧在python 2.6中的 118个字符):
c,z,k=locals,[0],'_[1]'
p=lambda n:[len(c()[k])and map(sum,zip(z+c()[k][-1],c()[k][-1]+z))or[1]for _ in range(n)]
Run Code Online (Sandbox Code Playgroud)
说明:
[1][1]并制造[0,1]和[1,0][(0,1),(1,0)]并用sum来映射.用法(漂亮的打印,实际上是代码-golf xD):
result = p(10)
lines = [" ".join(map(str, x)) for x in result]
for i in lines:
print i.center(max(map(len, lines)))
Run Code Online (Sandbox Code Playgroud)
输出:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 …Run Code Online (Sandbox Code Playgroud) algorithm code-golf combinatorics discrete-mathematics pascals-triangle
假设我有一个如下定义的二叉树数据结构
type 'a tree =
| Node of 'a tree * 'a * 'a tree
| Nil
Run Code Online (Sandbox Code Playgroud)
我有一个树的实例如下:
let x =
Node
(Node (Node (Nil,35,Node (Nil,40,Nil)),48,Node (Nil,52,Node (Nil,53,Nil))),
80,Node (Node (Nil,82,Node (Nil,83,Nil)),92,Node (Nil,98,Nil)))
Run Code Online (Sandbox Code Playgroud)
我正在尝试将树打印成易于理解的东西.最好,我想在控制台窗口中打印树,如下所示:
_______ 80 _______
/ \
_ 48 _ _ 92 _
/ \ / \
35 52 82 98
\ \ /
40 53 83
Run Code Online (Sandbox Code Playgroud)
有什么方法可以让我的树以这种格式输出?
有时我仍然试图将过程代码转换为功能代码.
是否有一个功能成语/片段列表映射到程序习语/片段?
编辑
由于似乎没有这些片段的集中式网站,我将其转变为社区维基.请在此粘贴任何程序 - >功能片段.
我写了以下函数:
let str2lst str =
let rec f s acc =
match s with
| "" -> acc
| _ -> f (s.Substring 1) (s.[0]::acc)
f str []
Run Code Online (Sandbox Code Playgroud)
如何知道F#编译器是否将其转换为循环?有没有办法在不使用Reflector的情况下找出答案(我没有使用Reflector的经验而且我不知道C#)?
编辑:另外,是否可以在不使用内部函数的情况下编写尾递归函数,或者循环是否需要驻留?
另外,F#std lib中是否有一个函数可以多次运行给定函数,每次都将最后一个输出作为输入?让我说我有一个字符串,我想在字符串上运行一个函数然后再次在结果字符串上运行它等等...
Google提供了大量在F#字典(或其他集合)中添加和删除条目的示例.但我没有看到相当于的例子
myDict["Key"] = MyValue;
Run Code Online (Sandbox Code Playgroud)
我试过了
myDict.["Key"] <- MyValue
Run Code Online (Sandbox Code Playgroud)
我也试图将词典声明为
Dictionary<string, mutable string>
Run Code Online (Sandbox Code Playgroud)
以及这方面的几个变种.然而,我都打不上的正确组合,但...如果它是实际上可能在F#.
编辑:违规代码是:
type Config(?fileName : string) =
let fileName = defaultArg fileName @"C:\path\myConfigs.ini"
static let settings =
dict[ "Setting1", "1";
"Setting2", "2";
"Debug", "0";
"State", "Disarray";]
let settingRegex = new Regex(@"\s*(?<key>([^;#=]*[^;#= ]))\s*=\s*(?<value>([^;#]*[^;# ]))")
do File.ReadAllLines(fileName)
|> Seq.map(fun line -> settingRegex.Match(line))
|> Seq.filter(fun mtch -> mtch.Success)
|> Seq.iter(fun mtch -> settings.[mtch.Groups.Item("key").Value] <- mtch.Groups.Item("value").Value)
Run Code Online (Sandbox Code Playgroud)
我得到的错误是:
System.NotSupportedException: This value may not be mutated
at Microsoft.FSharp.Core.ExtraTopLevelOperators.dict@37-2.set_Item(K key, V value)
at …Run Code Online (Sandbox Code Playgroud) 我可以在C++中轻松地做到这一点(注意:我没有测试它的正确性 - 它只是为了说明我正在尝试做什么):
const int BadParam = -1;
const int Success = 0;
int MyFunc(int param)
{
if(param < 0)
{
return BadParam;
}
//normal processing
return Success;
}
Run Code Online (Sandbox Code Playgroud)
但我无法弄清楚如何在F#早期退出例行程序.我想要做的是在输入错误时退出该功能,但如果输入正常则继续.我错过了F#的一些基本属性,还是因为我刚刚学习FP而以错误的方式解决问题?是failwith我在这里唯一的选择?
这是我到目前为止所得到的,它编译好了:
#light
module test1
(* Define how many arguments we're expecting *)
let maxArgs = 2;;
(* The indices of the various arguments on the command line *)
type ProgArguments =
| SearchString = 0
| FileSpec = 1;;
(* Various errorlevels which the app can return and …Run Code Online (Sandbox Code Playgroud) 我有一个序列{"1";"a";"2";"b";"3";"c";...}.
如何将此seq转换为 {("1","a");("2","b");("3","c");...}
我一直在研究使用F#进行开发,并且发现(对于我的情况)构建脚本以帮助我简化一些复杂的任务,我可以从中获得价值(目前).
我最常见的复杂任务是连接许多任务的文件(主要是SQL相关的).
我经常这样做,每次我尝试改进我的F#脚本来做到这一点.
到目前为止,这是我的最大努力:
open System.IO
let path = "C:\\FSharp\\"
let pattern = "*.txt"
let out_path = path + "concat.out"
File.Delete(out_path)
Directory.GetFiles(path, pattern)
|> Array.collect (fun file -> File.ReadAllLines(file))
|> (fun content -> File.WriteAllLines(out_path, content) )
Run Code Online (Sandbox Code Playgroud)
我确信其他人都有脚本,这使得他们有时候复杂/无聊的任务更容易.您曾经使用过哪些F#脚本或者您认为F#脚本的其他用途有用吗?
我发现改善F#的最佳方法是浏览其他脚本以获得有关如何处理特定情况的想法.希望这个问题将来会帮助我和其他人.:)
我发现了一篇关于生成可能感兴趣的F#脚本的文章:http: //blogs.msdn.com/chrsmith/archive/2008/09/12/scripting-in-f.aspx
我有一个函数,它的参数是常数,例如
let is_prime x = (test)
Run Code Online (Sandbox Code Playgroud)
但它非常大而且速度很慢。所以我希望它的结果只计算一次,而我可以随时调用它。
我试图以一种非函数式语言的方式做到这一点:
let _is_prime x = (test)
let mutable _is_prime_primes = []
let mutable _is_prime_tested = []
let is_prime x =
if List.exists (fun el -> el = x) _is_prime_primes then
true
else
if List.exists (fun el -> el = x) _is_prime_tested then
false
else
let result = _is_prime x
if result then _is_prime_primes <- x :: _is_prime_primes
_is_prime_tested <- x :: _is_prime_tested
result
Run Code Online (Sandbox Code Playgroud)
但是我想我深深错了。缓存这样的结果对于函数式语言来说必须是非常常见和简单的事情。