小编Cyb*_*bis的帖子

使用Haskell状态monad一个代码味?

上帝我讨厌"代码味"这个词,但我想不出更准确的东西.

我正在业余时间为Whitespace设计一个高级语言和编译器,以了解编译器构造,语言设计和函数编程(编译器是用Haskell编写的).

在编译器的代码生成阶段,我必须在遍历语法树时保持"状态" - 数据.例如,在编译流控制语句时,我需要为要跳转到的标签生成唯一的名称(从传入,更新和返回的计数器生成的标签,并且绝不能再次使用计数器的旧值).另一个例子是当我在语法树中遇到内联字符串文字时,它们需要永久转换为堆变量(在空白中,字符串最好存储在堆上).我目前正在处理状态monad中的整个代码生成模块来处理这个问题.

我被告知编写编译器是一个非常适合功能范例的问题,但我发现我的设计方式与我在C中设计它的方式大致相同(你真的可以用任何语言编写C语言 - 甚至Haskell w/state monads).

我想学习如何在Haskell中思考(而不是在函数范式中) - 而不是在C中使用Haskell语法.我真的应该尝试消除/最小化状态monad的使用,还是一个合法的功能"设计模式"?

monads haskell coding-style state-monad

57
推荐指数
3
解决办法
1万
查看次数

TDD如何使重构更容易?

我听说使用TDD开发的项目更容易重构,因为这种做法产生了一套全面的单元测试,如果任何更改破坏了代码,它将(希望)失败.然而,我所看到的所有这些例子都涉及重构实现 - 例如,用更高效的算法改变算法.

我发现重构架构在设计仍在制定的早期阶段更为常见.接口改变,添加和删除新类,甚至函数的行为可能会稍微改变(我认为我需要它来做这个,但它实际上需要这样做)等等......但是如果每个测试用例都紧密耦合对于这些不稳定的类,您每次更改设计时都不必不断地重写测试用例吗?

在TDD的什么情况下可以改变和删除测试用例?你怎么能确定改变测试用例不会破坏它们?此外,似乎必须同步一个全面的测试套件和不断变化的代码将是一个痛苦.我知道单元测试套件在维护期间可以提供很大的帮助,一旦软件构建完成,稳定并且运行正常,但是在游戏的后期TDD应该尽早提供帮助.

最后,关于TDD和/或重构的好书会解决这些问题吗?如果是这样,你会推荐哪一个?

tdd refactoring

27
推荐指数
3
解决办法
5068
查看次数

当模式匹配失败时,为什么Haskell列表推导不会导致错误?

我试图理解Haskell列表理解如何在模式匹配方面"在幕后"工作.以下ghci输出说明了我的观点:

Prelude> let myList = [Just 1, Just 2, Nothing, Just 3]
Prelude> let xs = [x | Just x <- myList]
Prelude> xs
[1,2,3]
Prelude>
Run Code Online (Sandbox Code Playgroud)

如您所见,它可以跳过"Nothing"并仅选择"Just"值.我知道List是一个monad,定义为(源自Real World Haskell,第14章):

instance Monad [] where
    return x = [x]
    xs >>= f = concat (map f xs)
    xs >> f = concat (map (\_ -> f) xs)
    fail _ = []
Run Code Online (Sandbox Code Playgroud)

因此,列表推导基本上为列表推导中选择的每个元素构建一个单例列表并将它们连接起来.如果模式匹配在某个步骤失败,则使用"失败"功能的结果.换句话说,"Just x"模式不匹配,因此在调用"concat"之前,[]用作占位符.这就解释了为什么"Nothing"似乎被忽略了.

我不明白的是,Haskell如何知道称之为"失败"功能?它是"编译魔术",还是你可以在Haskell中自己编写的功能?是否可以编写以下"select"函数以与列表推导相同的方式工作?

select :: (a -> b) -> [a] -> [b]
select (Just x -> x) myList       -- how to …
Run Code Online (Sandbox Code Playgroud)

haskell list-comprehension pattern-matching

20
推荐指数
3
解决办法
2438
查看次数

有没有静态的鸭型语言?

我申报会员时可以指定接口吗?

在思考了这个问题一段时间之后,我发现静态鸭式语言可能确实有效.为什么在编译时不能将预定义的类绑定到接口?例:

public interface IMyInterface
{
  public void MyMethod();
}

public class MyClass  //Does not explicitly implement IMyInterface
{
  public void MyMethod()  //But contains a compatible method definition
  {
    Console.WriteLine("Hello, world!");
  }
}

...

public void CallMyMethod(IMyInterface m)
{
  m.MyMethod();
}

...

MyClass obj = new MyClass();
CallMyMethod(obj);     // Automatically recognize that MyClass "fits" 
                       // MyInterface, and force a type-cast.
Run Code Online (Sandbox Code Playgroud)

你知道支持这种功能的任何语言吗?它会在Java或C#中有用吗?它在某种程度上存在根本缺陷吗?我知道你可以继承MyClass并实现接口或使用Adapter设计模式来完成同样的事情,但这些方法看似不必要的样板代码.

duck-typing language-design static-typing interface class

18
推荐指数
6
解决办法
3500
查看次数

帮助函数的命名约定是什么?

在函数式编程中,将任何"循环"代码优化为尾递归通常很重要.尾递归算法通常在两个函数之间分开,但是 - 一个用于设置基本情况,另一个用于实现实际循环.一个好的(尽管是学术的)例子是反向功能.

reverse :: [a] -> [a]
reverse = reverse_helper []

reverse_helper :: [a] -> [a] -> [a]
reverse_helper result [] = result
reverse_helper result (x:xs) = reverse_helper (x:result) xs
Run Code Online (Sandbox Code Playgroud)

"reverse_helper"并不是一个很好的描述性名称.但是,"reverse_recursive_part"只是尴尬.

你会对这样的帮助函数使用什么命名约定?

haskell functional-programming naming-conventions helper-functions

10
推荐指数
4
解决办法
5642
查看次数

Lisp In A Box - 为什么要启动服务器?

我已经决定回到LISP(自我的AI类以来没有使用过它)以便更好地使用函数式编程,所以我下载了Lisp In A Box(我们实际上在以前的类中使用过) CLISP和Emacs.

当我运行它时,它说:

在1617号港口连接.拿这个REPL,兄弟,也许它可以为你服务.

什么?所以我更仔细地查看了Lisp In A Box网页,发现了这个:

SLIME是Emacs的集成开发环境,它通过网络套接字与Common Lisp实现接口.有关SLIME的大量信息可以在CLiki上的SLIME节点上找到.SLIME手册在线提供PDF格式.

我有点理解SLIME是什么(对emacs的某种扩展,对吗?)但是为什么世界上是一个文本编辑器启动自己的服务器并连接到它?

lisp emacs slime lisp-in-a-box

9
推荐指数
2
解决办法
2403
查看次数

TDD - 什么时候可以写一个非失败的测试?

根据我的理解,在TDD中你必须首先编写一个失败的测试,然后编写代码使其通过,然后重构.但是,如果您的代码已经考虑了您要测试的情况怎么办?

例如,假设我是TDD的排序算法(这只是假设).我可能会为几个案例编写单元测试:

输入= 1,2,3
输出= 1,2,3

输入= 4,1,3,2
输出= 1,2,3,4
等...

为了让测试通过,我最终使用了一个快速的肮脏的泡泡排序.然后我重构并用更有效的合并排序算法替换它.后来,我意识到我们需要它是一个稳定的类型,所以我也为此编写了一个测试.当然,测试永远不会失败,因为merge-sort是一种稳定的排序算法!无论如何,我仍然需要这个测试,因为有人再次重构它以使用不同的,可能不稳定的排序算法.

这是否打破了始终编写失败测试的TDD口头禅?我怀疑有人会建议我浪费时间来实现一个不稳定的排序算法,只是为了测试测试用例,然后重新实现merge-sort.你经常遇到类似的情况,你做了什么?

tdd failing-tests

8
推荐指数
2
解决办法
1941
查看次数

网页完成加载时应该关注控件吗?

以下是我的意思的一些例子:

google.com - 焦点设置在"搜索"框中

gmail.google.com - 焦点设置在"用户名"字段中(实际上,大多数Web电子邮件客户端执行此操作).

stackoverflow,问一个问题 - 焦点设置在"标题"框中.

有时,这是一个方便的功能 - 例如,在Google上.但是,从可用性的角度来看,它真的被认为是登录页面上的一个很好的功能吗?

就个人而言,我经常输入我的用户名,开始输入我的密码,然后页面完成加载并将焦点重新放回用户名字段.不幸的是,由于我有复杂的密码迫使我在键入时查看键盘,我没注意到焦点转移时.对于站在我身后的人来说,我常常会在未屏蔽的用户名字段中键入我的密码.

另一种情况,虽然不那么危险但仍然很烦人,就是当我在我的主页仍在加载时在我的地址栏中输入网址时.然而,一旦它完成,如果我没有进入网址,焦点就会从我身上偷走并放在其他领域.

是否应对网站和/或浏览器进行编程,以便在用户已与网站或浏览器进行交互时不会改变焦点?像这样的问题会困扰普通(即非程序员)用户吗?

usability

8
推荐指数
1
解决办法
360
查看次数

在建模数据库时如何处理"特殊情况"数据?

我们的组织为客户提供各种服务(例如,网络托管,技术支持,定制编程等).我们网站上有一个页面,列出了所有可用的服务及其相应的价格.这是静态数据,但我的老板希望它全部从数据库中取出.

列出了大约100项服务.然而,其中只有两个具有"价格"的非数值(具体地,字符串"ISA"和"成本+ 8%" - 我真的不知道它们应该是什么意思,所以不要问我).

我不想仅仅因为这两个列表而使"价格"列成为varchar.我目前的做法是创建一个特殊的"price_display"字段,该字段为空白或包含要显示的文本以代替价格.这个解决方案感觉太像脏兮兮的黑客(它会不必要地使查询复杂化),那么有更好的解决方案吗?

database data-modeling

5
推荐指数
1
解决办法
362
查看次数

尝试添加ajax TabContainer,得到错误"控件集合无法修改,因为控件包含代码块(即<%...%>)."

我想在我的网页上添加一个ajax:TabContainer.我没有得到任何构建错误,但是当我尝试浏览到该页面时,它给出了错误:"控件集合无法修改,因为控件包含代码块(即<%...%>)." .

我重新下载了样本站点的Ajax Control Toolkit,在VS中打开了解决方案,为TabContainer运行了样本,并且运行正常.我认为它可能是Ajax Control Toolkit的另一个版本 - 但没有.这两个站点引用的AjaxControlToolkit.dll文件是相同的.为什么我不能让TabContainer在我的网站上运行?

还有一个问题,但我不知道它是否相关.我刚刚安装了Visual Studio 2008.一旦我打开我的网站,VS就会自动在工具箱中创建"AJAX Controls"选项卡,并用所有ajax控件填充它.在源代码中,所有控件都以"ajax"为前缀 - 即"<ajax:TabContainer runat ="server"...>".

但是,当我打开示例网站时,Visual studio在工具箱中创建了另一个选项卡 - "AjaxControlToolkit Components",其中包含与"AJAX Controls"中相同的所有控件.我不知道为什么它两次添加相同的控件(但奇怪的是,在工具箱中有不同的图标).在源代码中,所有控件都以"ajaxToolkit"为前缀 - 即"<ajaxToolkit:TabContainer runat ="server"...>".这里发生了什么?我只是希望在我的网站上使用强制TabContainer.

ajaxcontroltoolkit visual-studio-2008

1
推荐指数
1
解决办法
9236
查看次数

如何使用Python的'help()'函数报告错误?

作为一个业余爱好/学习项目,我正在用Python编写一个解析器生成器.我的一个代码文件名为"token.py" - 它包含几个用于将纯字符串转换为Token对象的类.我刚刚发现在Python中使用控制台中的"help()"函数会在包含"token.py"的目录中定义的任何模块引发错误.

这是重现错误的方法.使用以下文件创建新目录:

/New Folder
  main.py
  token.py
Run Code Online (Sandbox Code Playgroud)

将'token.py'留空.在main.py中,编写一个简单的函数 - 例如:

def test():
    pass
Run Code Online (Sandbox Code Playgroud)

然后,在你的Python控制台中,导入'main'并调用'help(main.test)' - 这是你将得到的:

C:\New Folder>python
Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import main
>>> help(main.test)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python31\lib\site.py", line 428, in __call__
    import pydoc
  File "C:\Python31\lib\pydoc.py", line 55, in <module>
    import sys, imp, os, re, inspect, builtins, pkgutil …
Run Code Online (Sandbox Code Playgroud)

python namespaces

1
推荐指数
1
解决办法
496
查看次数