小编Lou*_*uis的帖子

懒惰评估与宏

我习惯于从Haskell那里进行懒惰的评估,并且发现自己因为我已经正确地使用了懒惰的评估而感到厌烦.这实际上是非常具有破坏性的,因为我使用的其他语言主要是懒得评估一些非常笨拙的东西,通常涉及自定义迭代器的推出等等.所以只是通过获取一定的了解,其实我已经自己做了在我原来的语言生产力.叹.

但我听说AST宏提供了另一种干净的方式来做同样的事情.我经常听到诸如"懒惰评估使宏多余"的陈述,反之亦然,主要来自于对Lisp和Haskell社区的争吵.

我已经涉足各种Lisp变种中的宏.它们看起来像是一种非常有组织的复制和粘贴代码块的方式,可以在编译时处理.他们当然不是Lispers认为的圣杯.但这几乎可以肯定是因为我无法正确使用它们.当然,让宏系统在与语言本身组合在一起的相同核心数据结构上工作是非常有用的,但它仍然基本上是一种复制和粘贴代码的有组织方式.我承认,基于与允许完全运行时更改的语言相同的AST的宏系统是强大的.

我想知道的是,如何使用宏来简明扼要地进行懒惰评估呢?如果我想逐行处理文件而不会搞砸整个事情,我只返回一个列表,其中有一个映射到它的行读取例程.这是DWIM的完美例子(尽我所能).我甚至不必考虑它.

我显然没有得到宏.我已经使用过它们并且在炒作时并没有特别留下深刻的印象.因此,我缺少一些我没有通过在线阅读文档获得的东西.有人可以向我解释这一切吗?

lisp macros scheme haskell lazy-evaluation

47
推荐指数
5
解决办法
6157
查看次数

Python:在协同程序中产生Dict元素?

在我说一句话之前,让我感谢社区作为我最近编程查询权威位置.并假装那些称赞不是用文字表达的.无论如何,概率定律指出我偶然发现了使用多功能搜索栏找不到的东西,所以我决定第一次明确要求.也许我只是没有使用Pythonic-enough语言进行搜索.或许我在Googling/Stackoverflowing吮吸.而不管...

我正在玩Python协同程序和生成器.从我可以收集到的,你可以做任何生成器理解可以与生产者协同程序,尽管更冗长.我目前正在使用Python 3,尽管有关Python 2的任何答案都不会错过.

所以我假设以下代码片段是等价的:

one_to_three = (num for num in range(1, 4))
Run Code Online (Sandbox Code Playgroud)

...

def one_to_three():
    for num in range(1, 4):
        yield num

one_to_three_gen = one_to_three()
Run Code Online (Sandbox Code Playgroud)

它适用于我的Python安装.如果我忽略该代码中的冗余 - 如此常见的示例,我看到生成器理解很容易映射到生成器协同程序生成的生成器.作为Pragmatic博士,我尝试将相同的概念映射到dicts,因为dict理解已经存在,我认为这两个是等价的:

one_to_three_doubles = {num : num * 2 for num in range(1, 4)}
Run Code Online (Sandbox Code Playgroud)

...

def one_to_three_doubles():
    for num in range(1, 4):
        yield num : num * 2

one_to_three_doubles_gen = one_to_three_doubles()
Run Code Online (Sandbox Code Playgroud)

第一个可以工作,但第二个没有.它标记第3行冒号上的语法错误.

现在,要么我在语法上略微下滑,要么我对生产者协程如何工作有很大的误解.我怀疑它的失败是因为你不能让coroutine返回列表而不是生成器,但我真的不知道.

所以是的,修正这个错误基本上就是我所要求的; 提前致谢.我更喜欢一个答案,告诉我答案,而不是给我一个全新的方法来实现结果,但显然如果这是唯一的方法......

python dictionary list-comprehension generator

17
推荐指数
2
解决办法
1万
查看次数

实模式x86 ASM:基础知识如何完成?

我目前正在boot.s源代码中读取第一个Linux内核的文件(假设0.01确实是第一个公开发布).

我知道C和ASM,后者比前者少得多.即便如此,我似乎能够理解并基本上掌握源文件中的代码.

这个文件让我很困惑.我现在意识到这是因为它处于实模式,而不是保护模式.不用说,我以前从未见过以实模式编写的ASM代码.保护模式是在我出生之前运行的事实模式x86操作系统,所以这是可以预料的.

这是我想要更好地理解的例程:

/*
 * This procedure turns off the floppy drive motor, so
 * that we enter the kernel in a known state, and
 * don't have to worry about it later.
 */
kill_motor:
    push dx
    mov dx,#0x3f2
    mov al,#0
    outb
    pop dx
    ret
Run Code Online (Sandbox Code Playgroud)

向上看outb,我发现它用于将字节传递给计算机上的端口.我将基于C文档猜测这个场景将"stop motor"字节作为第一个参数传递,并将软盘驱动器端口号作为第二个参数.

这个界面是BIOS提供的吗?还是直接通过软驱?我假设BIOS对所有基本设备的基本操作都有节俭的"驱动程序".

这就是我难倒的地方:似乎数字之类的东西#0x3f2正在被掏出来.它们显然是硬件端口号或其他东西.这个文件上撒有这样的数字,没有解释他们所指的是什么.在哪里可以找到一个全面的参考资料,显示他们可以从实模式接收的所有硬件端口和控制编号?此外,似乎文件在整个启动过程中使用硬编码的内存地址在内存中移动内核.在哪里可以找到有关在实模式下可以写入哪些内存地址范围的指南?

我还阅读了Linus关于重新编程中断的评论,以避免BIOS和内部硬件中断之间的冲突.我不会撒谎,这是我的头脑.

帮助会很棒; 谷歌似乎很少涉及这个话题,万一你想知道.

assembly operating-system real-mode bios low-level

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

C++ Lambdas,捕获,智能Ptrs和堆栈:为什么这有效?

我一直在玩C++ 11中的一些新功能,我试着编写以下程序,期望它不起作用.令我惊讶的是,它(在Linux x86上的GCC 4.6.1上带有'std = c ++ 0x'标志):

#include <functional>
#include <iostream>
#include <memory>

std::function<int()> count_up_in_2s(const int from) {
    std::shared_ptr<int> from_ref(new int(from));
    return [from_ref]() { return *from_ref += 2; };
}

int main() {
    auto iter_1 = count_up_in_2s(5);
    auto iter_2 = count_up_in_2s(10);

    for (size_t i = 1; i <= 10; i++)
        std::cout << iter_1() << '\t' << iter_2() << '\n'
        ;
}
Run Code Online (Sandbox Code Playgroud)

我希望每次执行返回的lambda时都会删除'from_ref'.这是我的推理:一旦运行count_up_in_2s,from_ref就会从堆栈中弹出,但由于返回的lambda不是必须立即运行,因为它已经返回,所以在相同的引用之前,没有另一个引用存在很短的时间当lambda实际运行时推回,所以shared_ptr的引用计数不应该为零,然后删除数据?

除非C++ 11的lambda捕获比我给它的功能更加聪明,如果是的话,我会很高兴的.如果是这种情况,我可以假设C++ 11的变量捕获将允许所有词法范围/闭包技巧la Lisp,只要/ something /正在处理动态分配的内存吗?我可以假设所有捕获的引用都将保留,直到lambda本身被删除,允许我以上述方式使用smart_ptrs吗?

如果这是我认为的那样,这是不是意味着C++ 11允许表达高阶编程?如果是这样,我认为C++ 11委员会做得很好=)

c++ variables lambda memory-management c++11

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

以线程安全方式发布非线程安全对象字段

我遇到了Java并发问题.是的,我看了几乎完全相同标题的问题,但他们似乎都在寻求微妙的不同之处.是的,我已经阅读了Java Concurrency in Practice.是的,我能看到为什么它是事实上的对话题参考.是的,我已经阅读了专门针对线程安全类中的发布字段的部分.是的,我仍然会问一个关于Java的并发问题,不管我知道有人会简单地指出我那本书.

这让我很难过 - 我知道你可以通过确保具有易变性和/或同步访问的正确读/写命令,以线程安全的方式轻松发布可变原语字段,并且64位原语需要具有原子访问权限由于其读/写操作缺乏原子性.我知道在需要在类的字段的特定"快照"上执行的代码块上使用锁.我完全了解原子包和AtomicLong <>等好东西.

但是我仍然对将非线程安全对象作为线程安全类中的字段发布感到困惑.

从我所看到的,一旦你在getter中返回对它的引用,你就可以在任何时候对调用者提供前所未有的对象内容访问权限.此外,如果你给一个setter,你允许他们将对象引用设置为一个对象,它们可以在他们使用setter的对象之外控制它们.

无论如何,我无法解决从非线程安全对象组成线程安全类而不使它们全部私有/受保护并在类中为所有非线程安全对象创建所有非线程安全对象的线程安全包装器方法让该类的用户可能想要使用.这听起来像是一个样板噩梦.

我的意思是,如果你将一个AtomicReference <>返回给getter中的对象,他们可以使用.get()来再次获得对它的非同步访问.

我考虑的另一种方法是让所有getter基于旧的获取非线程安全对象的新副本,这意味着修改将是无关紧要的,同样适用于setter.但是Java有一个无可救药的复杂系统来克隆对象(浅拷贝与深拷贝与特定拷贝等),这有点让我无法做到这一点.而且,这是如此低效,以至于它不会比使用像Clojure那样为不变性而设计的语言更快.事实上,考虑到这些语言允许多条不可变数据在幕后共享相同的数据,它可能会慢得多.

那么,如何以可行的方式编写已发布的非线程安全对象的线程安全类?

提前致谢.

java concurrency composition thread-safety mutability

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

Perl:特殊变量是否安全?

我正在阅读关于$ @全局变量的一些问题,以及它是如何在它被处理之前被破坏的,因为成功的eval擦拭干净.

但是,如果它被并发线程中发生的错误所破坏呢?新的线程包说默认情况下不会共享内容,这意味着它是为数不多的主流语言之一"$ a = $ a;" 默认是确定性的(并且认为人们说大型项目中C#和Java比Perl更好).但我不确定特殊的全局变量.

我的直觉表明他们就像任何其他变量一样,因此他们不会被分享.我的大脑的本能说'让我们检查一下Stackoverflow上的向导'.

我检查了Perldoc上的线程教程,它涵盖了共享部分中的常规变量,但似乎继续进行而没有覆盖特殊变量.

即使我没有首先对它们进行本地化,我是否可以使用特殊变量而不会被其他线程破坏?例如,我可以从$ @中提取一个值而不必担心并行线程中发生的错误吗?

concurrency perl multithreading sharing non-deterministic

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

Ruby:操纵迭代器?

关于创建单向,延迟评估,可能无限的迭代器,我遇到了Ruby的问题.基本上,我正在尝试使用Ruby,就像我使用Haskell列表,以及在较小程度上使用Python生成器.

并不是我本身不理解它们; 我只是不知道如何像其他语言一样随意使用它们,而且我也不确定Ruby中的哪些方法会将它们变成背后的数组,将整个序列卸载到内存中是不必要的.

是的,我一直在研究Ruby参考手册.其实半小时,专注.或者显然不是.

例如,如果我要实现卡片组,它在Python中看起来像这样(未经测试):

# Python 3

from itertools import chain, count

face_ranks =
    dict(
        zip(
            ('jack', 'queen', 'king', 'ace'),
            count(11)))

sorted_deck =
    map(
        lambda suit:
            map(
                lambda rank:
                    {
                        'rank' : rank,
                        'suit' : suit
                    },
                chain(
                    range(2, 11),
                    face_ranks.keys())),
        ('clubs', 'diamonds', 'hearts', 'spades'))
Run Code Online (Sandbox Code Playgroud)

那么,我如何在Ruby中完成这项工作,完全避免使用数组呢?请注意,据我所知,上面的代码只使用元组和生成器:在任何时候都不会将整个序列转储到内存中,就像我使用了数组一样.我对上面的代码可能是错的,但是你得到了我想要的东西.

我如何链接迭代器(如Python的chain())?如何生成无限范围的迭代器(如Python的count())?如何在迭代器中添加一个数组(比如将元组传递给Python的链())而不将整个过程转换为数组?

我见过解决方案,但它们涉及阵列或不必要的复杂性,如光纤.

在Python中,我可以像数组一样简单地操作和抛出迭代器.我几乎可以把它们当作Haskell列表来对待,我最熟悉的就是它,而且在编码时我的想法就是这样.我对Ruby数组感到不舒服,这就是为什么我寻求其替代品的帮助.

我已经设法在互联网上获取有关它的信息,但我找不到任何涵盖Ruby中这种数据结构的基本操作?有帮助吗?

ruby arrays iterator enumerator

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

C99:限制指针记录线程安全?

这个问题不是关于限制的技术用法,更多是关于主观使用的.虽然我可能会误解技术上的限制是多么有限,但在这种情况下,你应该随意烧我,以便在错误的前提下提出问题.

以下是我到目前为止如何使用限制的两个示例:

如果我有一个指向一系列不可变字符的函数的函数,我不说它是受限制的,因为允许其他人在函数执行的同时通过自己的指针访问数据,例如从另一个并行执行线.数据没有被修改,所以没问题.

但是,如果函数接受指向它可能修改的可变字符序列的指针,我说它是受限制的,因为在执行期间绝对不应该从任何指针(显然是函数使用的参数)中访问数据.由于可能不一致的数据导致的功能.它还说明了数据被修改的可能性,因此编码器知道不读取陈旧数据,并且他们在访问时应该使用内存屏障或者其他......

我没有编写很多C代码,所以我很容易对我在这里假设的内容提出错误.这是对限制的正确用法吗?在这种情况下值得做吗?

我还假设一旦限制指针在函数返回时弹出堆栈,那么数据可以再次通过任何其他指针自由访问,并且限制仅持续与受限指针一样长.我知道这依赖于遵循规则的编码器,因为通过"非官方"指针访问受限数据是UB.

我有这一切吗?

编辑:

我只想说清楚我已经知道它绝对没有阻止用户通过多个线程访问数据,我也知道C89甚至不知道'线程'是什么.

但是考虑到可以通过引用修改参数的任何上下文,很明显它不能在函数运行时被访问.这对强制执行线程安全没有任何作用,但它确实清楚地表明在执行函数期间通过自己的指针修改数据需要您自担风险.

即使线程完全脱离了等式,你仍然允许在我认为正确的场景中进一步优化.

即便如此,感谢您迄今为止的所有权威答案.我是否赞成我喜欢的所有答案,或者仅仅是我接受的答案?如果接受不止一个怎么办?对不起,我是新来的,现在我会更全面地浏览常见问题解答......

c concurrency c99 mutability restrict-qualifier

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

项目特定的DSL是否是责任?

我从一个类似的问题中提出了这个问题,我在评论中提到了我收到的许多重要答案之一.我最初询问AST宏,这主要引起了Lispers非常详细和深思熟虑的回应.谢谢.

懒惰评估与宏

我在评论中提出的问题是项目特定的DSL是否真的是一个好主意.当然,这是完全主观的 - 毕竟,当你用一种非常富有表现力的语言写作时,你在哪里画出富有表现力的API和实际的DSL之间的界限?例如,我认为大多数Rubyist称之为"DSL"的实际上只是精心设计的API而已.

请注意,我说项目特定的 API.我认为很多人不会反对使用正则表达式或SQL这样做有意义.

但尽管如此,我认为我们都可以在API和DSL之间划清界限.当然,他们都是真正的API,但无论如何.

在一个极端你有Lisp,似乎通过宏积极鼓励DSLs.另一方面,你喜欢Java,而DSL几乎是不可能的.

DSL的支持者会争辩说,它们会增加灵活性,表现力并增加一致性(例如,使用与语言自身数字相同的运算符的自定义数字对象).

批评者会说他们可以导致除了DSL编写者之外没有人知道的子语言,从根本上杀死了拥有不同编程语言的观点,导致代码无人能理解,因为与API 接口的方式不同.

我得说,我在很多方面同意双方的意见.由于缺乏表现力,一些Java API只是简单的讨厌.尽管如此,我通常可以在不阅读文档的情况下总结出正在发生的事情 - 这对于定制的DSL来说是丝毫不可能的.也许DSL的支持者认为你应该总是阅读API文档.我不同意,但我也离题了.

但是让我们来看看目前的一些大语言.C#和Java,即.他们俩都没有"做"DSL,但他们非常受欢迎.这正是因为他们容许的事情喜欢的DSL,让平庸的编码器生产出的代码,仍然理解?

事实上DSL是否允许平庸的编码器产生难以穿透的垃圾,这就是为什么Lisp没有尽可能多地使用它的原因,尽管DSL可以在右手中看起来像什么?

lisp java api macros dsl

5
推荐指数
2
解决办法
440
查看次数

Perl:保证常量的单一评估吗?

两天内我第三个问题.有些人会说我不够努力研究,虽然我会说我正在帮助保持这个部分活跃:P无论哪种方式,我都在大声思索,希望得到一个答案.

不用多说了,让我引用常量 pragma文档中的声明:

当在表达式中使用常量时,Perl在编译时将其替换为其值,然后可以进一步优化表达式.

我只想明确一点:这是否意味着每个程序执行只评估所有表达式一次?因为它还说它们是使用内联子设备构建的,这使我觉得它本身就是每次使用的评估.我的意思是,如果你得到一个返回表达式的sub,它会根据每次调用重新评估它,对吧?除非他们使用封闭变量或状态变量来评估一次,但我不知道.

可以肯定的是,我可以保证这只会评估一次吗?

#!/usr/bin/perl

use 5.014;
use autodie;
use strict;
use warnings;

use constant TEST => do {
    say 'Testing...';
    5;
};

say TEST foreach (1..4);
Run Code Online (Sandbox Code Playgroud)

在这个特殊的例子中,我可以; '测试......'只打印一次.但是我保留了所有表达式吗?

耶耶耶.我应该在CPAN 上使用Readonly.不幸的是,我来自Python的思路,你应该坚持尽可能多地做一些标准的做法,因此我坚持使用复古常数,因为它是一个核心的实用主义.

基本上,如果我将一个长的复杂排序/ grep/map管道放入常量,我可以100%保证只进行一次评估吗?

perl const constants pragma immutability

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

PHP 5.3:地球上的这个变量是如何定义的?

今天我正在玩一些PHP,做我通常做的事情,当我尝试一种我不知道或生锈的语言:写一个小蹩脚的纸牌游戏.

第一项任务是推出一个包含所有可用卡片的分类卡组.这是我的(失败)尝试:

<?php

$sorted_deck = array_map(
    function($suit) {
        $card = function($rank) {
            return array(
                'suit' => $suit
                , 'rank' => $rank
            );
        };
        return
            array_map($card, range(2, 10))
            + array_map($card, array('jack', 'queen', 'king', 'ace'))
            ;
    }
    , array('clubs', 'diamonds', 'hearts', 'spades')
);

?>
Run Code Online (Sandbox Code Playgroud)

我不确定这段代码是否在逻辑上是正确的; 我匆匆写了一遍.但即使我确实想检查它,我也不能,因为它失败了以下消息:'Undefined variable:suit'.

只有一个地方使用$ suit,这就是$ card函数.鉴于$ card函数是在具有$ suit作为其参数的匿名函数内分配的,当然可以访问它,对吧?此外,必须定义它,因为PHP自己的array_map函数是从我的定义值数组中提供参数的函数.

我转换function card($rank) { ...$card = function($rank) { ...想,也许前者使得全球像Perl的子做,从而使内部变量访问.但后者也不起作用,令我惊讶的是.

任何人都可以给我一个正确的方向吗?

php variables undefined php-5.3

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

Perl:后期Coderef参数的语法糖?

使用子原型,我们可以定义我们自己的看起来像map或grep的subs.也就是说,第一个coderef参数的语法比普通的匿名子语言短.例如:

sub thunked (&) { $_[0] }

my $val = thunked { 2 * 4 };
Run Code Online (Sandbox Code Playgroud)

这里工作得很好,因为第一个参数是coderef.但是对于后面的参数,它很简单,不能正确解析.

我制作了一个with子程序,旨在使GTK2代码更清晰.它看起来像这样(未经测试,因为它是假设的代码):

use 5.012;
use warnings;

use Gtk2 '-init';    

sub with ($&) {
    local $_ = $_[0];
    $_[1]->();
    $_;
}

for (Gtk2::Window->new('toplevel')) {
    $_->set_title('Test Application');
    $_->add(with Gtk2::VBox->new {
        my $box = $_;
        $box->add(Gtk2::Button->new("Button $_")) for (1..4);
    });
    $_->show_all;
}
Gtk2->main;
Run Code Online (Sandbox Code Playgroud)

它不起作用,因为with需要将块作为第一个参数才能使用漂亮的语法.有什么方法可以把它拉下来吗?

syntax perl lambda closures programming-languages

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