TL; DR:向Array.prototype和Function.prototype添加任何非内置函数将导致IE8本机JSON解析器在解析包含数组的任何JSON时获得堆栈溢出,但仅当您还传递了reviver函数时进入JSON.parse().
这开始是一个问题,但我回答了我自己的原始问题,所以现在我会问:任何人都可以想到这个IE8错误的解决办法,不涉及删除修改Array.prototype和Function的所有JS库.原型?
原始问题:
我有大约13k的JSON数据要解析.数据的结构是具有单个值的对象,该值是嵌套数组.
{ 'value':[[ stuff ], [ more stuff], [ etc ]] }
Run Code Online (Sandbox Code Playgroud)
我正在使用json2.js,它在可用时遵循浏览器本机JSON.parse.我正在将一个reviver函数传递给JSON.parse来正确处理日期.当IE8处于IE7仿真模式(导致它使用基于脚本的json2.js解析器)时,一切正常.当IE8处于IE8模式(导致它使用浏览器本机JSON解析器)时,它会出现"堆栈空间不足"错误.当然,Firefox和Chrome可以与浏览器原生的JSON解析器一起使用.
我把它缩小到这个:如果我将一个do-nothing reviver函数传递给JSON.parse,那么IE8本机解析器会获得堆栈溢出.如果我传入没有reviver函数,IE8本机解析器工作正常,除了它不能正确解析日期.
// no error:
JSON.parse(stuff);
// "out of stack space" error:
JSON.parse(stuff, function(key, val) { return val; });
Run Code Online (Sandbox Code Playgroud)
我将使用我的JSON数据,看看数据的更少或更少的嵌套可以避免错误,但我想知道是否有人之前已经看过这个,或者有任何其他建议的解决方法.IE8已经足够慢了,因为这个bug而禁用该浏览器的原生JSON将是一种耻辱.
更新:在其他情况下,使用不同的JSON数据,当我使用具有reviver功能的IE8本机解析器时,我收到javascript错误"$ lineinfo is undefined",如果我不使用reviver函数则没有错误.字符串"$ lineinfo"不会出现在我的任何源代码中的任何位置.
更新2:实际上,这个问题似乎是由Prototype 1.6.0.3引起的.在我添加到Prototype库之前,我无法在隔离的测试页面中重现它.
更新3:
prototype.js打破IE8原生JSON解析器的原因是:向Array.prototype和Function.prototype添加任何非内置函数将导致IE8本机JSON解析器在解析包含数组的任何JSON时获得堆栈溢出,但只有当你还将一个reviver函数传递给JSON.parse()时.
Prototype库为Array.prototype和Function.prototype添加了函数,但这同样适用于执行相同操作的任何其他库.IE JSON解析器中的这个错误由Prototype和Ext公开,但不是jQuery.我还没有测试过任何其他框架.
这是一个完全独立的问题再现.如果删除Function.prototype行或Array.prototype行,或从JSON字符串中删除该数组,则不会出现"堆栈空间不足"错误.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript">
Function.prototype.test1 = function() { };
Array.prototype.test2 = function() { };
window.onload = function()
{
alert(JSON.parse('{ "foo": …Run Code Online (Sandbox Code Playgroud) F#的编译器用哪种语言编写?
我听说F#的编译器是用F#编写的
(F#编译器的每个下一个版本都是用它以前的版本编写的)
但是:
1.如果它是真的,不能谷歌.
2.如果是的话,用哪种语言编写F#编译器的第一个版本?
在C#中,可以像这样定义一个类型成员常量:
class Foo { public const int Bar = 600; }
Run Code Online (Sandbox Code Playgroud)
IL看起来像这样.
.field public static literal int32 Bar = int32(600)
Run Code Online (Sandbox Code Playgroud)
我如何在Visual F#/ FSharp中做同样的事情?
我试过这个无济于事:
[<Sealed>]
type Foo() =
[<Literal>]
let Bar = 600
Run Code Online (Sandbox Code Playgroud) 我正在为Lift公司创建一个小应用程序.我是Scala/Lift的新手,所以我正在利用这个机会练习.现在,我对使用什么ORM系统有疑问.
一方面,Mapper是Lift默认值.另一方面,我已经读过它在某些领域并不好,并且会被Record取代(这还没有很好的文档记录,所以像我这样的新用户很难遵循).
与Mapper相反,我们有JPA:标准的Java,经过测试和强大的ORM以及像Hibernate这样的可信实现,但不完全是"scala-ish",并且由于它与Lift的集成,你放弃了Mapper默认提供的功能.
我已经在邮件列表上看到一些断言,JPA正在成为Lift的方式,但它似乎并不普遍.有人可以为这件事带来一些启示吗?
谢谢!
某处是否有有效前缀运算符名称列表?我无法找到一个,但我注意到一些曾经在最后一个CTP中作为前缀运算符有效的运算符在RC中不再有效.
let (~--) (str:string) = [str];;
-----^^^
stdin(4,6): error FS1208: Invalid operator definition.
Prefix operator definitions must use a valid prefix operator name.
Run Code Online (Sandbox Code Playgroud)
编辑:
Brian的链接包括以下有效前缀运算符列表:
! (or repetitions of !)
~ (or repetitions of ~)
+
-
+.
-.
%
%%
&
&&
Run Code Online (Sandbox Code Playgroud)
我的链接下面仅列出了这些运算符:
~
!
?
Run Code Online (Sandbox Code Playgroud)
快速测试表明,MSDN文档似乎不符合语言规范.谢谢,Brian.
关于FileSystemWatcher的一直困扰我的事情之一是它为文件的单个逻辑更改触发多个事件的方式.我知道它为什么会发生,但我不想要关心 - 我只想重新整理文件一次,而不是连续4-6次.理想情况下,只有在给定文件完成更改时才会触发事件,而不是沿途的每一步.
多年来,我已经提出了各种解决方案来解决这个问题,不同程度的丑陋.我认为Reactive Extensions将是最终解决方案,但是我做得不对,我希望有人可以指出我的错误.
我有一个扩展方法:
public static IObservable<IEvent<FileSystemEventArgs>> GetChanged(this FileSystemWatcher that)
{
return Observable.FromEvent<FileSystemEventArgs>(that, "Changed");
}
Run Code Online (Sandbox Code Playgroud)
最终,我希望在给定的时间段内为每个文件名获得一个事件 - 这样一行中具有单个文件名的四个事件将减少为一个事件,但如果同一个文件被修改,我不会丢失任何内容时间.BufferWithTime听起来像是理想的解决方案
var bufferedChange = watcher.GetChanged()
.Select(e => e.EventArgs.FullPath)
.BufferWithTime(TimeSpan.FromSeconds(1))
.Where(e => e.Count > 0)
.Select(e => e.Distinct());
Run Code Online (Sandbox Code Playgroud)
当我订阅这个observable时,对受监视文件的单个更改会连续四次触发我的订阅方法,这相当于失败了.如果我删除了Distinct()呼叫,我看到四个呼叫中的每一个都包含两个相同的事件 - 所以有一些缓冲正在进行.增加TimeSpan传递给BufferWithTime似乎没有任何影响 - 我高达20秒没有任何行为改变.
这是我第一次涉足Rx,所以我可能错过了一些明显的东西.我做错了吗?有更好的方法吗?谢谢你的任何建议......
看一下FSharp.Core和PowerPack中的源代码,我看到很多接受带有两个或更多参数的函数的高阶函数都使用FSharpFunc.Adapt.例如:
let mapi f (arr: ResizeArray<_>) =
let f = FSharpFunc<_,_,_>.Adapt(f)
let len = length arr
let res = new ResizeArray<_>(len)
for i = 0 to len - 1 do
res.Add(f.Invoke(i, arr.[i]))
res
Run Code Online (Sandbox Code Playgroud)
文档FSharpFunc.Adapt相当薄.这是我们应该在任何时候使用具有类似签名的高阶函数时使用的一般最佳实践吗?只有多次调用传入函数?它的优化程度是多少?我们应该Adapt在任何地方使用,或者只是很少使用?
谢谢你的时间.
...或者,如何通过它们实现的接口过滤一系列类?
假设我有一系列从Foo继承的对象,a seq<#Foo>.换句话说,我的序列将包含Foo的四个不同子类中的一个或多个.
每个子类实现一个不同的独立接口,它与其他子类实现的接口不共享.
现在我需要将此序列过滤为仅实现特定接口的项目.
C#版本很简单:
void MergeFoosIntoList<T>(IEnumerable<Foo> allFoos, IList<T> dest)
where T : class
{
foreach (var foo in allFoos)
{
var castFoo = foo as T;
if (castFoo != null)
{
dest.Add(castFoo);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我可以使用F#中的LINQ:
let mergeFoosIntoList (foos:seq<#Foo>) (dest:IList<'a>) =
System.Linq.Enumerable.OfType<'a>(foos)
|> Seq.iter dest.Add
Run Code Online (Sandbox Code Playgroud)
但是,我觉得应该有一种更惯用的方法来实现它.我以为这会起作用......
let mergeFoosIntoList (foos:seq<#Foo>) (dest:IList<'a>) =
foos
|> Seq.choose (function | :? 'a as x -> Some(x) | _ -> None)
|> Seq.iter dest.Add
Run Code Online (Sandbox Code Playgroud)
然而,编纂者抱怨:? 'a- 告诉我:
从类型'b到'a的这种运行时强制或类型测试涉及基于该程序点之前的信息的不确定类型.某些类型不允许运行时类型测试.需要进一步的类型注释.
我无法弄清楚要添加的更多类型注释.还有的接口之间没有任何关系'a …
如何不对ToString重载采取零参数?零参数ToString是System.Object的一部分!
编辑以响应近距离投票: 由于我无法将构建服务器升级到.NET 4.5,有没有办法让这个代码与.NET 4.0/VS 2010编译器一起工作?没有给我的超载一个完全不同的名字,这只是不酷.
我想最简单的解决方法是将我的ToString重载重命名为其他东西,但这很奇怪.
这是一个简单的复制品.您可以在此处下载包含此代码的解决方案的zip文件:http://dl.dropbox.com/u/1742470/CS1501_Repro.zip
在VS 2010中编译该解决方案将失败"CS1501:方法'ToString'没有重载需要0个参数".在VS 2012中编译它将工作得很好.在这两种情况下,我们都以.NET Framework 4为目标.
F#
namespace CS1501_Repro.FSharp
open System
[<Serializable>]
type MyDiscriminatedUnion =
| Foo of int list
| Bar of string
| Baz of int
| Fizz of float
| Buzz of DateTimeOffset
override this.ToString() =
"Zero Arguments"
member this.ToString(lookup:Func<int,string>) =
"One Argument"
Run Code Online (Sandbox Code Playgroud)
C#
using System;
using CS1501_Repro.FSharp;
namespace CS1501_Repro.CSharp
{
public class Caller
{ …Run Code Online (Sandbox Code Playgroud) DataContractJsonSerializer为F#记录类型创建JSON,其中包含每个属性名称后面的"@"字符.有没有人知道是否有可能获得没有这个尾随符号的JSON?
{"heart_rate@":20,"latitude@":45.0,"longitude@":108.0,"name@":"Rambo"}
Run Code Online (Sandbox Code Playgroud)
这是我用来输出此示例的脚本
#r "System.Xml"
#r "System.Runtime.Serialization"
open System.Text
open System.Runtime.Serialization.Json
open System.IO
type Update = {
name: string;
latitude: decimal;
longitude: decimal;
heart_rate: int}
let update = {name = "Rambo"; latitude = 45.0m; longitude = 108.0m; heart_rate = 20}
let serializer = new DataContractJsonSerializer( typeof<Update> )
let stream = new MemoryStream()
let data = serializer.WriteObject(stream, update)
let updateData = stream.ToArray()
let json = (Encoding.UTF8.GetString(updateData))
printfn "%s" json
Run Code Online (Sandbox Code Playgroud)